diff --git a/Cargo.lock b/Cargo.lock index 99efae8fa..04aa1ba4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -293,12 +293,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -732,12 +726,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - [[package]] name = "crypto-common" version = "0.1.6" @@ -851,18 +839,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - [[package]] name = "funty" version = "2.0.0" @@ -969,26 +945,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "indexmap" version = "2.1.0" @@ -1099,6 +1055,14 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "mcl_rust" +version = "1.0.2" +source = "git+https://github.com/herumi/mcl-rust.git#db8e9a639d27fffb167bc48159ef2e3178b347dc" +dependencies = [ + "cc", +] + [[package]] name = "memchr" version = "2.6.4" @@ -1196,32 +1160,6 @@ dependencies = [ "group", ] -[[package]] -name = "parity-scale-codec" -version = "3.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "paste" version = "1.0.14" @@ -1279,27 +1217,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] - [[package]] name = "proc-macro2" version = "1.0.69" @@ -1468,6 +1385,7 @@ dependencies = [ "rayon", "rust-kzg-arkworks3-sppark", "rust-kzg-arkworks3-sppark-wlc", + "smallvec", ] [[package]] @@ -1557,29 +1475,19 @@ dependencies = [ [[package]] name = "rust-kzg-mcl" -version = "0.0.1" -dependencies = [ - "blst", - "cc", - "hex", - "kzg", - "libc", - "num_cpus", - "once_cell", - "primitive-types", - "rayon", -] - -[[package]] -name = "rust-kzg-mcl-bench" version = "0.1.0" dependencies = [ "blst", "criterion 0.5.1", + "hex", "kzg", "kzg-bench", + "libc", + "mcl_rust", + "once_cell", "rand", - "rust-kzg-mcl", + "rayon", + "smallvec", ] [[package]] @@ -1614,12 +1522,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - [[package]] name = "rustc_version" version = "0.3.3" @@ -1812,12 +1714,6 @@ dependencies = [ name = "sppark_bal" version = "0.1.0" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "subtle" version = "2.5.0" @@ -1900,23 +1796,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - [[package]] name = "typenum" version = "1.17.0" @@ -1929,18 +1808,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - [[package]] name = "unicode-ident" version = "1.0.12" @@ -2227,15 +2094,6 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" -[[package]] -name = "winnow" -version = "0.5.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32" -dependencies = [ - "memchr", -] - [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 77eac2260..8eef487f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,13 +9,11 @@ members = [ "blst-sppark", "kzg", "kzg-bench", - "mcl/kzg", - "mcl/kzg-bench", + "mcl", "zkcrypto", "constantine", "rust-eth-kzg-benches", ] - [profile.bench] lto = "thin" diff --git a/arkworks3/Cargo.toml b/arkworks3/Cargo.toml index 4a1c419df..1ec01c764 100644 --- a/arkworks3/Cargo.toml +++ b/arkworks3/Cargo.toml @@ -16,6 +16,7 @@ hex = "0.4.3" rand = { version = "0.8.5", optional = true } libc = { version = "0.2.148", default-features = false } rayon = { version = "1.8.0", optional = true } +smallvec = { version = "1.11.1", features = ["const_generics"] } rust-kzg-arkworks3-sppark = { path = "../arkworks3-sppark", version = "0.1.0", optional = true } rust-kzg-arkworks3-sppark-wlc = { path = "../arkworks3-sppark-wlc", version = "0.1.0", optional = true } diff --git a/arkworks3/benches/das.rs b/arkworks3/benches/das.rs index d0daeccd8..e5e4eece4 100644 --- a/arkworks3/benches/das.rs +++ b/arkworks3/benches/das.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::das::bench_das_extension; -use rust_kzg_arkworks3::kzg_proofs::FFTSettings; +use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; fn bench_das_extension_(c: &mut Criterion) { diff --git a/arkworks3/benches/eip_4844.rs b/arkworks3/benches/eip_4844.rs index 4f6e8000c..d03dd56e0 100644 --- a/arkworks3/benches/eip_4844.rs +++ b/arkworks3/benches/eip_4844.rs @@ -6,7 +6,7 @@ use kzg::eip_4844::{ }; use kzg_bench::benches::eip_4844::bench_eip_4844; use rust_kzg_arkworks3::eip_4844::load_trusted_setup_filename_rust; -use rust_kzg_arkworks3::kzg_proofs::{FFTSettings, KZGSettings}; +use rust_kzg_arkworks3::kzg_proofs::{LFFTSettings as FFTSettings, LKZGSettings as KZGSettings}; use rust_kzg_arkworks3::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine, ArkG2}; use rust_kzg_arkworks3::utils::PolyData; diff --git a/arkworks3/benches/fft.rs b/arkworks3/benches/fft.rs index 26d1b4ed0..3ca428554 100644 --- a/arkworks3/benches/fft.rs +++ b/arkworks3/benches/fft.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::fft::{bench_fft_fr, bench_fft_g1}; -use rust_kzg_arkworks3::kzg_proofs::FFTSettings; +use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::{ArkFr, ArkG1}; fn bench_fft_fr_(c: &mut Criterion) { diff --git a/arkworks3/benches/recover.rs b/arkworks3/benches/recover.rs index 7e031ccc5..62172c430 100644 --- a/arkworks3/benches/recover.rs +++ b/arkworks3/benches/recover.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::recover::bench_recover; -use rust_kzg_arkworks3::kzg_proofs::FFTSettings; +use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; use rust_kzg_arkworks3::utils::PolyData; diff --git a/arkworks3/benches/zero_poly.rs b/arkworks3/benches/zero_poly.rs index b987af86e..07e274cd6 100644 --- a/arkworks3/benches/zero_poly.rs +++ b/arkworks3/benches/zero_poly.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::zero_poly::bench_zero_poly; -use rust_kzg_arkworks3::kzg_proofs::FFTSettings; +use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; use rust_kzg_arkworks3::utils::PolyData; diff --git a/arkworks3/src/poly.rs b/arkworks3/src/poly.rs index 01199a7d8..8e3176885 100644 --- a/arkworks3/src/poly.rs +++ b/arkworks3/src/poly.rs @@ -1,251 +1,130 @@ -use super::kzg_proofs::FFTSettings; -use super::utils::{blst_poly_into_pc_poly, PolyData}; +use super::kzg_proofs::LFFTSettings; +use super::utils::PolyData; use crate::kzg_types::ArkFr as BlstFr; -use crate::utils::pc_poly_into_blst_poly; -use crate::zero_poly::pad_poly; -use ark_bls12_381::Fr; -use ark_poly::univariate::DensePolynomial; -use ark_poly::UVPolynomial; -use ark_std::{log2, Zero}; use kzg::common_utils::{log2_pow2, next_pow_of_2}; use kzg::{FFTFr, FFTSettings as FFTSettingsT, Fr as FrTrait, Poly}; -use std::cmp::min; -pub fn poly_inverse(b: &PolyData, output_len: usize) -> Result { - if b.coeffs.is_empty() { - return Err(String::from("b.coeffs is empty")); +pub fn poly_flip(input: &PolyData) -> Result { + let mut output = PolyData::new(0); + for i in 0..input.len() { + output.coeffs.push(input.coeffs[input.coeffs.len() - i - 1]); } + Ok(output) +} - if BlstFr::is_zero(&b.coeffs[0]) { - return Err(String::from("b.coeffs[0] is zero")); - } +impl PolyData { + pub fn _poly_norm(&self) -> Self { + let mut ret = self.clone(); - let mut output = PolyData { - coeffs: vec![BlstFr::zero(); output_len], - }; - if b.coeffs.len() == 1 { - output.coeffs[0] = b.coeffs[0].inverse(); - for i in 1..output_len { - output.coeffs[i] = BlstFr::zero(); + let mut temp_len: usize = ret.coeffs.len(); + while temp_len > 0 && ret.coeffs[temp_len - 1].is_zero() { + temp_len -= 1; } - return Ok(output); - } - let maxd = output_len - 1; - let scale = next_pow_of_2(log2_pow2(2 * output_len - 1)); - let fs = FFTSettings::new(scale).unwrap(); - - let mut tmp0: PolyData; - let mut tmp1: PolyData; - - output.coeffs[0] = b.coeffs[0].inverse(); - let mut d: usize = 0; - let mut mask: usize = 1 << log2(maxd); - - while mask != 0 { - d = 2 * d + usize::from((maxd & mask) != 0); - mask >>= 1; - - let len_temp: usize = min(d + 1, b.coeffs.len() + output.coeffs.len() - 1); - - tmp0 = poly_mul(b, &output, Some(&fs), len_temp).unwrap(); - - for i in 0..len_temp { - tmp0.coeffs[i] = tmp0.coeffs[i].negate(); + if temp_len == 0 { + ret.coeffs = Vec::new(); + } else { + ret.coeffs = ret.coeffs[0..temp_len].to_vec(); } - let fr_two = BlstFr { fr: Fr::from(2) }; - tmp0.coeffs[0] = tmp0.coeffs[0].add(&fr_two); - let len_temp2: usize = d + 1; - - tmp1 = poly_mul(&output, &tmp0, Some(&fs), len_temp2).unwrap(); - - if tmp1.coeffs.len() > output_len { - tmp1.coeffs = tmp1.coeffs[..output_len].to_vec(); - } - for i in 0..tmp1.coeffs.len() { - output.coeffs[i] = tmp1.coeffs[i]; - } + ret } - if d + 1 != output_len { - return Err(String::from("d + 1 is not equals to output_len")); - } - Ok(output) -} -pub fn poly_mul_direct(p1: &PolyData, p2: &PolyData, len: usize) -> Result { - let p1 = blst_poly_into_pc_poly(&p1.coeffs); - let p2 = blst_poly_into_pc_poly(&p2.coeffs); - if p1.is_zero() || p2.is_zero() { - Ok(pc_poly_into_blst_poly(DensePolynomial::zero())) - } else { - let mut result = vec![Fr::zero(); len]; - for (i, self_coeff) in p1.coeffs.iter().enumerate() { - for (j, other_coeff) in p2.coeffs.iter().enumerate() { - if i + j >= len { - break; - } - result[i + j] += &(*self_coeff * other_coeff); - } + pub fn poly_quotient_length(&self, divisor: &Self) -> usize { + if self.len() >= divisor.len() { + self.len() - divisor.len() + 1 + } else { + 0 } - let p = pc_poly_into_blst_poly(DensePolynomial::from_coefficients_vec(result)); - Ok(PolyData { - coeffs: pad_poly(&p, len).unwrap(), - }) } -} -pub fn poly_long_div(p1: &PolyData, p2: &PolyData) -> Result { - Ok(pc_poly_into_blst_poly( - &blst_poly_into_pc_poly(&p1.coeffs) / &blst_poly_into_pc_poly(&p2.coeffs), - )) -} + pub fn pad(&self, out_length: usize) -> Self { + let mut ret = Self { + coeffs: vec![BlstFr::zero(); out_length], + }; -pub fn poly_mul( - a: &PolyData, - b: &PolyData, - fs: Option<&FFTSettings>, - len: usize, -) -> Result { - if a.coeffs.len() < 64 || b.coeffs.len() < 64 || len < 128 { - poly_mul_direct(a, b, len) - } else { - poly_mul_fft(a, b, fs, len) - } -} - -pub fn poly_mul_fft( - a: &PolyData, - b: &PolyData, - fs: Option<&FFTSettings>, - len: usize, -) -> Result { - // Truncate a and b so as not to do excess work for the number of coefficients required. - let a_len = min(a.len(), len); - let b_len = min(b.len(), len); - let length = next_pow_of_2(a_len + b_len - 1); - - // If the FFT settings are NULL then make a local set, otherwise use the ones passed in. - let fs_p = if let Some(x) = fs { - x.clone() - } else { - let scale = log2_pow2(length); - FFTSettings::new(scale).unwrap() - }; + for i in 0..self.len().min(out_length) { + ret.coeffs[i] = self.coeffs[i]; + } - if length > fs_p.max_width { - return Err(String::from( - "length should be equals or less than FFTSettings max width", - )); + ret } - let a = PolyData { - coeffs: a.coeffs[..a_len].to_vec(), - }; - let b = PolyData { - coeffs: b.coeffs[..b_len].to_vec(), - }; - let a_pad = PolyData { - coeffs: pad_poly(&a, length).unwrap(), - }; - let b_pad = PolyData { - coeffs: pad_poly(&b, length).unwrap(), - }; - - let a_fft; - let b_fft; - #[cfg(feature = "parallel")] - { - if length > 1024 { - let mut a_fft_temp = vec![]; - let mut b_fft_temp = vec![]; - - rayon::join( - || a_fft_temp = fs_p.fft_fr(&a_pad.coeffs, false).unwrap(), - || b_fft_temp = fs_p.fft_fr(&b_pad.coeffs, false).unwrap(), - ); - - a_fft = a_fft_temp; - b_fft = b_fft_temp; - } else { - a_fft = fs_p.fft_fr(&a_pad.coeffs, false).unwrap(); - b_fft = fs_p.fft_fr(&b_pad.coeffs, false).unwrap(); + pub fn flip(&self) -> Result { + let mut ret = PolyData { + coeffs: vec![BlstFr::default(); self.len()], + }; + for i in 0..self.len() { + ret.coeffs[i] = self.coeffs[self.coeffs.len() - i - 1] } - } - #[cfg(not(feature = "parallel"))] - { - a_fft = fs_p.fft_fr(&a_pad.coeffs, false).unwrap(); - b_fft = fs_p.fft_fr(&b_pad.coeffs, false).unwrap(); - } - let mut ab_fft = a_pad; - let mut ab = b_pad; - for i in 0..length { - ab_fft.coeffs[i] = a_fft[i].mul(&b_fft[i]); + Ok(ret) } - ab.coeffs = fs_p.fft_fr(&ab_fft.coeffs, true).unwrap(); + pub fn mul_fft(&self, multiplier: &Self, output_len: usize) -> Result { + let length = next_pow_of_2(self.len() + multiplier.len() - 1); - let data_len = min(len, length); - let mut out = PolyData::new(len); - - for i in 0..data_len { - out.coeffs[i] = ab.coeffs[i]; - } - for i in data_len..len { - out.coeffs[i] = BlstFr::zero(); - } + let scale = log2_pow2(length); + let fft_settings = LFFTSettings::new(scale).unwrap(); + + let a_pad = self.pad(length); + let b_pad = multiplier.pad(length); + + let a_fft: Vec; + let b_fft: Vec; + + #[cfg(feature = "parallel")] + { + if length > 1024 { + let mut a_fft_temp = vec![]; + let mut b_fft_temp = vec![]; + + rayon::join( + || a_fft_temp = fft_settings.fft_fr(&a_pad.coeffs, false).unwrap(), + || b_fft_temp = fft_settings.fft_fr(&b_pad.coeffs, false).unwrap(), + ); + + a_fft = a_fft_temp; + b_fft = b_fft_temp; + } else { + a_fft = fft_settings.fft_fr(&a_pad.coeffs, false).unwrap(); + b_fft = fft_settings.fft_fr(&b_pad.coeffs, false).unwrap(); + } + } - Ok(out) -} + #[cfg(not(feature = "parallel"))] + { + // Convert Poly to values + a_fft = fft_settings.fft_fr(&a_pad.coeffs, false).unwrap(); + b_fft = fft_settings.fft_fr(&b_pad.coeffs, false).unwrap(); + } -pub fn poly_fast_div(dividend: &PolyData, divisor: &PolyData) -> Result { - if divisor.coeffs.is_empty() { - return Err(String::from("divisor coeffs are empty")); - } + // Multiply two value ranges + let mut ab_fft = a_fft; + ab_fft.iter_mut().zip(b_fft).for_each(|(a, b)| { + *a = a.mul(&b); + }); - if divisor.coeffs[divisor.coeffs.len() - 1].is_zero() { - return Err(String::from("divisor coeffs last member is zero")); - } + // Convert value range multiplication to a resulting polynomial + let ab = fft_settings.fft_fr(&ab_fft, true).unwrap(); + drop(ab_fft); - let m = dividend.coeffs.len() - 1; - let n = divisor.coeffs.len() - 1; + let mut ret = PolyData { + coeffs: vec![BlstFr::zero(); output_len], + }; - if n > m { - return Ok(PolyData::new(0)); - } + let range = ..output_len.min(length); + ret.coeffs[range].clone_from_slice(&ab[range]); - if divisor.coeffs[divisor.coeffs.len() - 1].is_zero() { - return Err(String::from("divisor coeffs last member is zero")); + Ok(ret) } - let mut out = PolyData::new(0); - - if divisor.len() == 1 { - for i in 0..dividend.len() { - out.coeffs - .push(dividend.coeffs[i].div(&divisor.coeffs[0]).unwrap()); + pub fn mul(&mut self, multiplier: &Self, output_len: usize) -> Result { + if self.len() < 64 || multiplier.len() < 64 || output_len < 128 { + // Tunable parameter + self.mul_direct(multiplier, output_len) + } else { + self.mul_fft(multiplier, output_len) } - return Ok(out); - } - - let a_flip = poly_flip(dividend).unwrap(); - let b_flip = poly_flip(divisor).unwrap(); - - let inv_b_flip = poly_inverse(&b_flip, m - n + 1).unwrap(); - let q_flip = poly_mul(&a_flip, &inv_b_flip, None, m - n + 1).unwrap(); - - out = poly_flip(&q_flip).unwrap(); - - Ok(PolyData { - coeffs: out.coeffs[..m - n + 1].to_vec(), - }) -} - -pub fn poly_flip(input: &PolyData) -> Result { - let mut output = PolyData::new(0); - for i in 0..input.len() { - output.coeffs.push(input.coeffs[input.coeffs.len() - i - 1]); } - Ok(output) } diff --git a/arkworks3/src/recover.rs b/arkworks3/src/recover.rs index c57f0c24d..8ec10fd3d 100644 --- a/arkworks3/src/recover.rs +++ b/arkworks3/src/recover.rs @@ -1,5 +1,5 @@ use crate::consts::SCALE_FACTOR; -use crate::kzg_proofs::FFTSettings; +use crate::kzg_proofs::LFFTSettings; use crate::kzg_types::ArkFr as BlstFr; use crate::utils::PolyData; @@ -82,10 +82,10 @@ pub fn unscale_poly(p: &mut PolyData) { } } } -impl PolyRecover for PolyData { +impl PolyRecover for PolyData { fn recover_poly_coeffs_from_samples( samples: &[Option], - fs: &FFTSettings, + fs: &LFFTSettings, ) -> Result { if !samples.len().is_power_of_two() { return Err(String::from("samples lenght has to be power of 2")); @@ -212,7 +212,7 @@ impl PolyRecover for PolyData { fn recover_poly_from_samples( samples: &[Option], - fs: &FFTSettings, + fs: &LFFTSettings, ) -> Result { let reconstructed_poly = Self::recover_poly_coeffs_from_samples(samples, fs)?; diff --git a/arkworks3/tests/bls12_381.rs b/arkworks3/tests/bls12_381.rs index 4c5031cef..6f9babc22 100644 --- a/arkworks3/tests/bls12_381.rs +++ b/arkworks3/tests/bls12_381.rs @@ -47,7 +47,6 @@ mod tests { } #[test] - #[should_panic] pub fn fr_div_by_zero_() { fr_div_by_zero::(); } diff --git a/arkworks3/tests/consts.rs b/arkworks3/tests/consts.rs index 20d237682..880e69d71 100644 --- a/arkworks3/tests/consts.rs +++ b/arkworks3/tests/consts.rs @@ -6,12 +6,12 @@ mod tests { }; use rust_kzg_arkworks3::consts::SCALE2_ROOT_OF_UNITY; use rust_kzg_arkworks3::kzg_proofs::expand_root_of_unity; - use rust_kzg_arkworks3::kzg_proofs::FFTSettings; + use rust_kzg_arkworks3::kzg_proofs::LFFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; #[test] fn roots_of_unity_out_of_bounds_fails_() { - roots_of_unity_out_of_bounds_fails::(); + roots_of_unity_out_of_bounds_fails::(); } #[test] @@ -26,7 +26,7 @@ mod tests { #[test] fn new_fft_settings_is_plausible_() { - new_fft_settings_is_plausible::(); + new_fft_settings_is_plausible::(); } #[test] diff --git a/arkworks3/tests/das.rs b/arkworks3/tests/das.rs index f4576684c..714a383d1 100644 --- a/arkworks3/tests/das.rs +++ b/arkworks3/tests/das.rs @@ -1,16 +1,16 @@ #[cfg(test)] mod tests { use kzg_bench::tests::das::{das_extension_test_known, das_extension_test_random}; - use rust_kzg_arkworks3::kzg_proofs::FFTSettings; + use rust_kzg_arkworks3::kzg_proofs::LFFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; #[test] fn das_extension_test_known_() { - das_extension_test_known::(); + das_extension_test_known::(); } #[test] fn das_extension_test_random_() { - das_extension_test_random::(); + das_extension_test_random::(); } } diff --git a/arkworks3/tests/eip_4844.rs b/arkworks3/tests/eip_4844.rs index 7c6e27b9b..41d4dbbac 100644 --- a/arkworks3/tests/eip_4844.rs +++ b/arkworks3/tests/eip_4844.rs @@ -22,7 +22,9 @@ mod tests { }; use rust_kzg_arkworks3::consts::SCALE2_ROOT_OF_UNITY; use rust_kzg_arkworks3::eip_4844::load_trusted_setup_filename_rust; - use rust_kzg_arkworks3::kzg_proofs::{expand_root_of_unity, FFTSettings, KZGSettings}; + use rust_kzg_arkworks3::kzg_proofs::{ + expand_root_of_unity, LFFTSettings, LKZGSettings as KZGSettings, + }; use rust_kzg_arkworks3::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine, ArkG2}; use rust_kzg_arkworks3::utils::PolyData; @@ -43,7 +45,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -60,7 +62,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -79,7 +81,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -101,7 +103,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -123,7 +125,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -145,7 +147,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -165,7 +167,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -185,7 +187,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -205,7 +207,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -225,7 +227,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -243,7 +245,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -261,7 +263,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -279,7 +281,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -293,7 +295,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -311,7 +313,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, diff --git a/arkworks3/tests/fft_fr.rs b/arkworks3/tests/fft_fr.rs index 0c778d71e..ea621901b 100644 --- a/arkworks3/tests/fft_fr.rs +++ b/arkworks3/tests/fft_fr.rs @@ -4,26 +4,26 @@ mod batch_adder; mod tests { use kzg_bench::tests::fft_fr::{compare_sft_fft, inverse_fft, roundtrip_fft, stride_fft}; use rust_kzg_arkworks3::fft::{fft_fr_fast, fft_fr_slow}; - use rust_kzg_arkworks3::kzg_proofs::FFTSettings; + use rust_kzg_arkworks3::kzg_proofs::LFFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; #[test] fn compare_sft_fft_() { - compare_sft_fft::(&fft_fr_slow, &fft_fr_fast); + compare_sft_fft::(&fft_fr_slow, &fft_fr_fast); } #[test] fn roundtrip_fft_() { - roundtrip_fft::(); + roundtrip_fft::(); } #[test] fn inverse_fft_() { - inverse_fft::(); + inverse_fft::(); } #[test] fn stride_fft_() { - stride_fft::(); + stride_fft::(); } } diff --git a/arkworks3/tests/fft_g1.rs b/arkworks3/tests/fft_g1.rs index 89e15c590..7ffb35b3a 100644 --- a/arkworks3/tests/fft_g1.rs +++ b/arkworks3/tests/fft_g1.rs @@ -2,7 +2,7 @@ mod tests { use kzg_bench::tests::fft_g1::{compare_sft_fft, roundtrip_fft, stride_fft}; use rust_kzg_arkworks3::fft_g1::{fft_g1_fast, fft_g1_slow, make_data}; - use rust_kzg_arkworks3::kzg_proofs::FFTSettings; + use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::{ArkFr, ArkG1}; #[test] diff --git a/arkworks3/tests/poly.rs b/arkworks3/tests/poly.rs index 4460ffdf1..5c796f1a6 100644 --- a/arkworks3/tests/poly.rs +++ b/arkworks3/tests/poly.rs @@ -6,7 +6,7 @@ mod tests { poly_inverse_simple_0, poly_inverse_simple_1, poly_mul_direct_test, poly_mul_fft_test, poly_mul_random, poly_test_div, }; - use rust_kzg_arkworks3::kzg_proofs::FFTSettings; + use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; use rust_kzg_arkworks3::utils::PolyData; @@ -46,7 +46,6 @@ mod tests { } #[test] - #[should_panic] fn poly_div_by_zero_() { poly_div_by_zero::(); } diff --git a/arkworks3/tests/recover.rs b/arkworks3/tests/recover.rs index 9f53d88a3..1a552cf9e 100644 --- a/arkworks3/tests/recover.rs +++ b/arkworks3/tests/recover.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod recover_tests { use kzg_bench::tests::recover::*; - use rust_kzg_arkworks3::kzg_proofs::FFTSettings; + use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr as Fr; use rust_kzg_arkworks3::utils::PolyData; diff --git a/arkworks3/tests/zero_poly.rs b/arkworks3/tests/zero_poly.rs index a28463325..9cab5c154 100644 --- a/arkworks3/tests/zero_poly.rs +++ b/arkworks3/tests/zero_poly.rs @@ -4,7 +4,7 @@ mod tests { check_test_data, reduce_partials_random, test_reduce_partials, zero_poly_252, zero_poly_all_but_one, zero_poly_known, zero_poly_random, }; - use rust_kzg_arkworks3::kzg_proofs::FFTSettings; + use rust_kzg_arkworks3::kzg_proofs::LFFTSettings as FFTSettings; use rust_kzg_arkworks3::kzg_types::ArkFr; use rust_kzg_arkworks3::utils::PolyData; diff --git a/kzg-bench/src/benches/eip_4844.rs b/kzg-bench/src/benches/eip_4844.rs index 53dab60d8..57bb2a558 100644 --- a/kzg-bench/src/benches/eip_4844.rs +++ b/kzg-bench/src/benches/eip_4844.rs @@ -24,6 +24,10 @@ pub fn bench_eip_4844< compute_kzg_proof: &dyn Fn(&[TFr], &TFr, &TKZGSettings) -> Result<(TG1, TFr), String>, verify_kzg_proof: &dyn Fn(&TG1, &TFr, &TFr, &TG1, &TKZGSettings) -> Result, compute_blob_kzg_proof: &dyn Fn(&[TFr], &TG1, &TKZGSettings) -> Result, + compute_cells_and_kzg_proofs: &dyn Fn( + &[u8], + &TKZGSettings, + ) -> Result<(Vec>, Vec), String>, verify_blob_kzg_proof: &dyn Fn(&[TFr], &TG1, &TG1, &TKZGSettings) -> Result, verify_blob_kzg_proof_batch: &dyn Fn( &[Vec], @@ -100,6 +104,11 @@ pub fn bench_eip_4844< }) }); + c.bench_function("compute_cells_and_kzg_proofs", |b| { + let blob_bytes = generate_random_blob_bytes(&mut rng); + b.iter(|| compute_cells_and_kzg_proofs(&blob_bytes, &ts)) + }); + let mut group = c.benchmark_group("verify_blob_kzg_proof_batch"); for count in [1, 2, 4, 8, 16, 32, 64] { group.throughput(Throughput::Elements(count as u64)); diff --git a/mcl/kzg/.gitignore b/mcl/.gitignore similarity index 100% rename from mcl/kzg/.gitignore rename to mcl/.gitignore diff --git a/mcl/Cargo.toml b/mcl/Cargo.toml new file mode 100644 index 000000000..6e8986671 --- /dev/null +++ b/mcl/Cargo.toml @@ -0,0 +1,93 @@ +[package] +name = "rust-kzg-mcl" +version = "0.1.0" +edition = "2021" + +[dependencies] +blst = "0.3.11" +kzg = { path = "../kzg", default-features = false } +libc = { version = "0.2.148", default-features = false } +once_cell = { version = "1.18.0", features = ["critical-section"], default-features = false } +rand = { version = "0.8.5", optional = true } +rayon = { version = "1.8.0", optional = true } +smallvec = { version = "1.11.1", features = ["const_generics"] } +hex = { version = "0.4.3", default-features = false, features = ["alloc"] } +mcl_rust = { git = "https://github.com/herumi/mcl-rust.git" } + +[dev-dependencies] +criterion = "0.5.1" +kzg-bench = { path = "../kzg-bench" } +rand = "0.8.5" + +mcl_rust = { git = "https://github.com/herumi/mcl-rust.git" } + +[features] +default = [ + "std", + "rand", + "bgmw" +] +std = [ + "hex/std", + "kzg/std", + "libc/std", + "once_cell/std", +] +rand = [ + "dep:rand", + "kzg/rand", +] +parallel = [ + "dep:rayon", + "kzg/parallel" +] +bgmw = [ + "kzg/bgmw" +] +arkmsm = [ + "kzg/arkmsm" +] + +[[bench]] +name = "das" +harness = false + +[[bench]] +name = "fft" +harness = false + +[[bench]] +name = "poly" +harness = false + +[[bench]] +name = "kzg" +harness = false + +[[bench]] +name = "fk_20" +harness = false + +[[bench]] +name = "recover" +harness = false + +[[bench]] +name = "zero_poly" +harness = false + +[[bench]] +name = "eip_4844" +harness = false + +[[bench]] +name = "eip_7594" +harness = false + +[[bench]] +name = "lincomb" +harness = false + +[[bench]] +name = "trusted_setup" +harness = false diff --git a/mcl/README.md b/mcl/README.md deleted file mode 100644 index b20382b8a..000000000 --- a/mcl/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# KZG10 (Kate) Polynomial Commitments - -## About - -This is a KZG10 implmentation in Rust, heavily based on the Go implementation by protolambda https://github.com/protolambda/go-kzg. - -This repo also contains Herumi MCL, as I could not find a way to make the cargo crate for mcl_rust work, and it does seem abandoned. It can be found here: https://github.com/herumi/mcl-rust. - -## How to test/run - -First follow the steps in Herumi mcl (refer to the link above), then just run the following code in checked out dir: -To test without rayon: - -```bash -cargo test -- --test-threads 1 --nocapture -``` - -With rayon: -```bash -cargo test --features mcl_rust/parallel -- --test-threads 1 --nocapture -``` - -To run benchmarks, just run - -```bash -cargo bench -``` \ No newline at end of file diff --git a/mcl/kzg-bench/benches/shared_das.rs b/mcl/benches/das.rs similarity index 57% rename from mcl/kzg-bench/benches/shared_das.rs rename to mcl/benches/das.rs index 9a7dacdca..63ebc4e69 100644 --- a/mcl/kzg-bench/benches/shared_das.rs +++ b/mcl/benches/das.rs @@ -1,13 +1,10 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::das::bench_das_extension; -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::fk20_fft::FFTSettings; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; +use rust_kzg_mcl::types::fft_settings::MclFFTSettings; +use rust_kzg_mcl::types::fr::MclFr; fn bench_das_extension_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_das_extension::(c); + bench_das_extension::(c) } criterion_group! { diff --git a/mcl/benches/eip_4844.rs b/mcl/benches/eip_4844.rs new file mode 100644 index 000000000..32cf203df --- /dev/null +++ b/mcl/benches/eip_4844.rs @@ -0,0 +1,36 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use kzg::eip_4844::{ + blob_to_kzg_commitment_rust, bytes_to_blob, compute_blob_kzg_proof_rust, + compute_kzg_proof_rust, verify_blob_kzg_proof_batch_rust, verify_blob_kzg_proof_rust, + verify_kzg_proof_rust, +}; +use kzg_bench::benches::eip_4844::bench_eip_4844; +use rust_kzg_mcl::{ + eip_4844::load_trusted_setup_filename_rust, + types::{ + fft_settings::MclFFTSettings, + fp::MclFp, + fr::MclFr, + g1::{MclG1, FsG1Affine}, + g2::MclG2, + kzg_settings::MclKZGSettings, + poly::MclPoly, + }, +}; + +fn bench_eip_4844_(c: &mut Criterion) { + bench_eip_4844::( + c, + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_kzg_proof_rust, + &verify_kzg_proof_rust, + &compute_blob_kzg_proof_rust, + &verify_blob_kzg_proof_rust, + &verify_blob_kzg_proof_batch_rust, + ); +} + +criterion_group!(benches, bench_eip_4844_); +criterion_main!(benches); diff --git a/mcl/benches/eip_7594.rs b/mcl/benches/eip_7594.rs new file mode 100644 index 000000000..5b5718293 --- /dev/null +++ b/mcl/benches/eip_7594.rs @@ -0,0 +1,16 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use kzg::eip_4844::{blob_to_kzg_commitment_rust, bytes_to_blob}; +use kzg_bench::benches::eip_7594::bench_eip_7594; +use rust_kzg_mcl::{eip_4844::load_trusted_setup_filename_rust, eip_7594::MclBackend}; + +fn bench_eip_7594_(c: &mut Criterion) { + bench_eip_7594::( + c, + &load_trusted_setup_filename_rust, + &bytes_to_blob, + &blob_to_kzg_commitment_rust, + ); +} + +criterion_group!(benches, bench_eip_7594_); +criterion_main!(benches); diff --git a/mcl/kzg-bench/benches/shared_fft.rs b/mcl/benches/fft.rs similarity index 51% rename from mcl/kzg-bench/benches/shared_fft.rs rename to mcl/benches/fft.rs index 352e46ba1..611bb2aac 100644 --- a/mcl/kzg-bench/benches/shared_fft.rs +++ b/mcl/benches/fft.rs @@ -1,19 +1,15 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::fft::{bench_fft_fr, bench_fft_g1}; -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::data_types::g1::G1; -use rust_kzg_mcl::fk20_fft::FFTSettings; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; +use rust_kzg_mcl::types::fft_settings::MclFFTSettings; +use rust_kzg_mcl::types::fr::MclFr; +use rust_kzg_mcl::types::g1::MclG1; fn bench_fft_fr_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_fft_fr::(c); + bench_fft_fr::(c); } fn bench_fft_g1_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_fft_g1::(c); + bench_fft_g1::(c); } criterion_group! { diff --git a/mcl/benches/fk_20.rs b/mcl/benches/fk_20.rs new file mode 100644 index 000000000..42166708f --- /dev/null +++ b/mcl/benches/fk_20.rs @@ -0,0 +1,23 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use kzg_bench::benches::fk20::{bench_fk_multi_da, bench_fk_single_da}; + +use rust_kzg_mcl::eip_7594::MclBackend; +use rust_kzg_mcl::types::fk20_multi_settings::MclFK20MultiSettings; +use rust_kzg_mcl::types::fk20_single_settings::MclFK20SingleSettings; +use rust_kzg_mcl::utils::generate_trusted_setup; + +fn bench_fk_single_da_(c: &mut Criterion) { + bench_fk_single_da::(c, &generate_trusted_setup) +} + +fn bench_fk_multi_da_(c: &mut Criterion) { + bench_fk_multi_da::(c, &generate_trusted_setup) +} + +criterion_group! { + name = benches; + config = Criterion::default().sample_size(10); + targets = bench_fk_single_da_, bench_fk_multi_da_ +} + +criterion_main!(benches); diff --git a/mcl/benches/kzg.rs b/mcl/benches/kzg.rs new file mode 100644 index 000000000..4d75a0691 --- /dev/null +++ b/mcl/benches/kzg.rs @@ -0,0 +1,20 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use kzg_bench::benches::kzg::{bench_commit_to_poly, bench_compute_proof_single}; +use rust_kzg_mcl::eip_7594::MclBackend; +use rust_kzg_mcl::utils::generate_trusted_setup; + +fn bench_commit_to_poly_(c: &mut Criterion) { + bench_commit_to_poly::(c, &generate_trusted_setup) +} + +fn bench_compute_proof_single_(c: &mut Criterion) { + bench_compute_proof_single::(c, &generate_trusted_setup) +} + +criterion_group! { + name = benches; + config = Criterion::default().sample_size(10); + targets = bench_commit_to_poly_, bench_compute_proof_single_ +} + +criterion_main!(benches); diff --git a/mcl/benches/lincomb.rs b/mcl/benches/lincomb.rs new file mode 100644 index 000000000..f00bd3811 --- /dev/null +++ b/mcl/benches/lincomb.rs @@ -0,0 +1,18 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use kzg_bench::benches::lincomb::bench_g1_lincomb; +use rust_kzg_mcl::kzg_proofs::g1_linear_combination; +use rust_kzg_mcl::types::fp::MclFp; +use rust_kzg_mcl::types::fr::MclFr; +use rust_kzg_mcl::types::g1::{MclG1, FsG1Affine}; + +fn bench_g1_lincomb_(c: &mut Criterion) { + bench_g1_lincomb::(c, &g1_linear_combination); +} + +criterion_group! { + name = benches; + config = Criterion::default().sample_size(100); + targets = bench_g1_lincomb_ +} + +criterion_main!(benches); diff --git a/mcl/kzg-bench/benches/shared_poly.rs b/mcl/benches/poly.rs similarity index 57% rename from mcl/kzg-bench/benches/shared_poly.rs rename to mcl/benches/poly.rs index 94a778152..b371ebdf4 100644 --- a/mcl/kzg-bench/benches/shared_poly.rs +++ b/mcl/benches/poly.rs @@ -1,13 +1,10 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::poly::bench_new_poly_div; -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::kzg10::Polynomial; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; +use rust_kzg_mcl::types::fr::MclFr; +use rust_kzg_mcl::types::poly::MclPoly; fn bench_new_poly_div_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_new_poly_div::(c); + bench_new_poly_div::(c); } criterion_group! { diff --git a/mcl/benches/recover.rs b/mcl/benches/recover.rs new file mode 100644 index 000000000..091ff4660 --- /dev/null +++ b/mcl/benches/recover.rs @@ -0,0 +1,15 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use kzg_bench::benches::recover::bench_recover; +use rust_kzg_mcl::types::{fft_settings::MclFFTSettings, fr::MclFr, poly::MclPoly}; + +pub fn bench_recover_(c: &mut Criterion) { + bench_recover::(c) +} + +criterion_group! { + name = benches; + config = Criterion::default().sample_size(10); + targets = bench_recover_ +} + +criterion_main!(benches); diff --git a/mcl/benches/trusted_setup.rs b/mcl/benches/trusted_setup.rs new file mode 100644 index 000000000..cb14833bc --- /dev/null +++ b/mcl/benches/trusted_setup.rs @@ -0,0 +1,35 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use kzg::eip_4844::load_trusted_setup_rust; +use kzg_bench::benches::trusted_setup::bench_load_trusted_setup; +use rust_kzg_mcl::{ + eip_4844::load_trusted_setup_filename_rust, + types::{ + fft_settings::MclFFTSettings, + fp::MclFp, + fr::MclFr, + g1::{MclG1, FsG1Affine}, + g2::MclG2, + kzg_settings::MclKZGSettings, + poly::MclPoly, + }, +}; + +fn bench_load_trusted_setup_(c: &mut Criterion) { + bench_load_trusted_setup::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + c, + &load_trusted_setup_filename_rust, + &load_trusted_setup_rust, + ); +} + +criterion_group!(benches, bench_load_trusted_setup_); +criterion_main!(benches); diff --git a/mcl/kzg-bench/benches/shared_zero_poly.rs b/mcl/benches/zero_poly.rs similarity index 52% rename from mcl/kzg-bench/benches/shared_zero_poly.rs rename to mcl/benches/zero_poly.rs index 133c0ba57..143132de4 100644 --- a/mcl/kzg-bench/benches/shared_zero_poly.rs +++ b/mcl/benches/zero_poly.rs @@ -1,14 +1,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::zero_poly::bench_zero_poly; -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::fk20_fft::FFTSettings; -use rust_kzg_mcl::kzg10::Polynomial; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; +use rust_kzg_mcl::types::{fft_settings::MclFFTSettings, fr::MclFr, poly::MclPoly}; fn bench_zero_poly_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_zero_poly::(c); + bench_zero_poly::(c); } criterion_group! { diff --git a/mcl/build.rs b/mcl/build.rs new file mode 100644 index 000000000..7e448ec1b --- /dev/null +++ b/mcl/build.rs @@ -0,0 +1,25 @@ +use std::env; +use std::process::Command; + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let top_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let opt = if cfg!(target_arch = "x86_64") { + "" + } else { + "-DCMAKE_CXX_COMPILER=clang++" + }; + + let cmd = format!( + "cd {out} && cmake {top}/mcl -DMCL_STATIC_LIB=ON -DMCL_STANDALONE=ON {opt} && make -j", + out = out_dir, + top = top_dir, + opt = opt + ); + Command::new("sh") + .args(["-c", &cmd]) + .output() + .expect("fail"); + let s = format!("cargo:rustc-link-search=native={}/lib", out_dir); + println!("{}", s); +} diff --git a/mcl/kzg-bench/.gitignore b/mcl/kzg-bench/.gitignore deleted file mode 100644 index f315ad9fc..000000000 --- a/mcl/kzg-bench/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by Cargo -# will have compiled files and executables -debug/ -target/ - -# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries -# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html -# Cargo.lock - -# These are backup files generated by rustfmt -**/*.rs.bk - -# MSVC Windows builds of rustc generate these, which store debugging information -*.pdb \ No newline at end of file diff --git a/mcl/kzg-bench/Cargo.toml b/mcl/kzg-bench/Cargo.toml deleted file mode 100644 index 01f1d4d27..000000000 --- a/mcl/kzg-bench/Cargo.toml +++ /dev/null @@ -1,50 +0,0 @@ -[package] -name = "rust-kzg-mcl-bench" -version = "0.1.0" -edition = "2021" - -[dependencies] -rust-kzg-mcl = { path = '../kzg' } -blst = "0.3.11" -kzg = { path = "../../kzg" } -kzg-bench = { path = "../../kzg-bench" } - -[dev-dependencies] -rand = "0.8.5" -criterion = "0.5.1" - -[[bench]] -name = "shared_fk20" -harness = false - -[[bench]] -name = "shared_zero_poly" -harness = false - -[[bench]] -name = "shared_fft" -harness = false - -[[bench]] -name = "shared_poly" -harness = false - -[[bench]] -name = "shared_das" -harness = false - -[[bench]] -name = "shared_recover" -harness = false - -[[bench]] -name = "shared_kzg_proof" -harness = false - -[[bench]] -name = "shared_eip_4844" -harness = false - -[[bench]] -name = "shared_lincomb" -harness = false diff --git a/mcl/kzg-bench/benches/shared_eip_4844.rs b/mcl/kzg-bench/benches/shared_eip_4844.rs deleted file mode 100644 index 99da426d9..000000000 --- a/mcl/kzg-bench/benches/shared_eip_4844.rs +++ /dev/null @@ -1,28 +0,0 @@ -use rust_kzg_mcl::data_types::{fr::Fr, g1::G1, g2::G2}; -use rust_kzg_mcl::eip_4844::*; -use rust_kzg_mcl::fk20_fft::FFTSettings; -use rust_kzg_mcl::kzg10::Polynomial; -use rust_kzg_mcl::kzg_settings::KZGSettings; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; - -use criterion::{criterion_group, criterion_main, Criterion}; -use kzg_bench::benches::eip_4844::bench_eip_4844; - -fn bench_eip_4844_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_eip_4844::( - c, - &load_trusted_setup, - &blob_to_kzg_commitment, - &bytes_to_blob, - &compute_kzg_proof, - &verify_kzg_proof, - &compute_blob_kzg_proof, - &verify_blob_kzg_proof, - &verify_blob_kzg_proof_batch, - ); -} - -criterion_group!(benches, bench_eip_4844_,); -criterion_main!(benches); diff --git a/mcl/kzg-bench/benches/shared_fk20.rs b/mcl/kzg-bench/benches/shared_fk20.rs deleted file mode 100644 index 6efc218fb..000000000 --- a/mcl/kzg-bench/benches/shared_fk20.rs +++ /dev/null @@ -1,33 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use kzg_bench::benches::fk20::*; -use rust_kzg_mcl::data_types::{fr::Fr, g1::G1, g2::G2}; -use rust_kzg_mcl::fk20_fft::FFTSettings; -use rust_kzg_mcl::fk20_matrix::{FK20Matrix, FK20SingleMatrix}; -use rust_kzg_mcl::kzg10::Polynomial; -use rust_kzg_mcl::kzg_settings::KZGSettings; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; - -fn bench_fk_single_da_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_fk_single_da::( - c, - &KZGSettings::generate_trusted_setup, - ) -} - -fn bench_fk_multi_da_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_fk_multi_da::( - c, - &KZGSettings::generate_trusted_setup, - ) -} - -criterion_group! { - name = benches; - config = Criterion::default().sample_size(10); - targets = bench_fk_single_da_, bench_fk_multi_da_ -} - -criterion_main!(benches); diff --git a/mcl/kzg-bench/benches/shared_kzg_proof.rs b/mcl/kzg-bench/benches/shared_kzg_proof.rs deleted file mode 100644 index f67bd2404..000000000 --- a/mcl/kzg-bench/benches/shared_kzg_proof.rs +++ /dev/null @@ -1,32 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use kzg_bench::benches::kzg::{bench_commit_to_poly, bench_compute_proof_single}; -use rust_kzg_mcl::data_types::{fr::Fr, g1::G1, g2::G2}; -use rust_kzg_mcl::fk20_fft::FFTSettings; -use rust_kzg_mcl::kzg10::Polynomial; -use rust_kzg_mcl::kzg_settings::KZGSettings; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; - -fn bench_commit_to_poly_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_commit_to_poly::( - c, - &KZGSettings::generate_trusted_setup, - ); -} - -fn bench_compute_proof_single_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_compute_proof_single::( - c, - &KZGSettings::generate_trusted_setup, - ); -} - -criterion_group! { - name = benches; - config = Criterion::default().sample_size(10); - targets = bench_commit_to_poly_, bench_compute_proof_single_ -} - -criterion_main!(benches); diff --git a/mcl/kzg-bench/benches/shared_lincomb.rs b/mcl/kzg-bench/benches/shared_lincomb.rs deleted file mode 100644 index bf7823b14..000000000 --- a/mcl/kzg-bench/benches/shared_lincomb.rs +++ /dev/null @@ -1,19 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use kzg_bench::benches::lincomb::bench_g1_lincomb; -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::data_types::g1::{g1_linear_combination, G1}; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; - -fn bench_g1_lincomb_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_g1_lincomb::(c, &g1_linear_combination); -} - -criterion_group! { - name = benches; - config = Criterion::default().sample_size(10); - targets = bench_g1_lincomb_ -} - -criterion_main!(benches); diff --git a/mcl/kzg-bench/benches/shared_recover.rs b/mcl/kzg-bench/benches/shared_recover.rs deleted file mode 100644 index 242fe8b5b..000000000 --- a/mcl/kzg-bench/benches/shared_recover.rs +++ /dev/null @@ -1,20 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -use kzg_bench::benches::recover::bench_recover; -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::fk20_fft::FFTSettings; -use rust_kzg_mcl::kzg10::Polynomial; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; - -fn bench_recover_(c: &mut Criterion) { - assert!(init(CurveType::BLS12_381)); - bench_recover::(c); -} - -criterion_group! { - name = benches; - config = Criterion::default().sample_size(10); - targets = bench_recover_ -} - -criterion_main!(benches); diff --git a/mcl/kzg-bench/src/fft_common.rs b/mcl/kzg-bench/src/fft_common.rs deleted file mode 100644 index 50c39cd99..000000000 --- a/mcl/kzg-bench/src/fft_common.rs +++ /dev/null @@ -1,41 +0,0 @@ -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::fk20_fft::*; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; -use std::vec; - -#[test] -fn fftsettings_new_creates_valid_settings() { - // Arrange - assert!(init(CurveType::BLS12_381)); - // Act - let fft_settings = FFTSettings::new(4 + 5 + 1); - // Assert - let expected = vec![ - Fr::from_int(1), - Fr::from_str( - "21328829733576761151404230261968752855781179864716879432436835449516750606329", - 10, - ) - .unwrap(), - Fr::from_str( - "12531186154666751577774347439625638674013361494693625348921624593362229945844", - 10, - ) - .unwrap(), - Fr::from_str( - "36815421669481109810171413925233110915304823983913164224028689762034127238951", - 10, - ) - .unwrap(), - ]; - - // has lots more members, but checking the first few should point out whether the math is correct - let starting_equal = fft_settings - .expanded_roots_of_unity - .iter() - .zip(expected) - .all(|(a, b)| a.get_str(10) == b.get_str(10)); - - assert!(starting_equal); -} diff --git a/mcl/kzg-bench/src/lib.rs b/mcl/kzg-bench/src/lib.rs deleted file mode 100644 index cd13ac34e..000000000 --- a/mcl/kzg-bench/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -#[macro_use] -#[cfg(test)] -mod test_macro; -#[cfg(test)] -mod fft_common; -#[cfg(test)] -mod poly; -#[cfg(test)] -mod test; -#[cfg(test)] -mod shared_tests { - mod bls12_381; - mod consts; - mod das; - mod eip_4844; - mod fft_fr; - mod fft_g1; - mod finite; - mod fk20_proofs; - mod kzg_proofs; - mod poly; - mod recover; - mod zero_poly; -} diff --git a/mcl/kzg-bench/src/poly.rs b/mcl/kzg-bench/src/poly.rs deleted file mode 100644 index ccbf8863d..000000000 --- a/mcl/kzg-bench/src/poly.rs +++ /dev/null @@ -1,138 +0,0 @@ -use rust_kzg_mcl::data_types::fr::Fr; -use rust_kzg_mcl::kzg10::*; -use rust_kzg_mcl::mcl_methods::init; -use rust_kzg_mcl::CurveType; -use std::vec; - -#[test] -fn polynomial_new_works_with_valid_params() { - // Arrange - assert!(init(CurveType::BLS12_381)); - let coefficients = vec![1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13]; - // Act - // Assert - let _poly = Polynomial::from_i32(&coefficients); -} - -#[test] -fn polynomial_eval_at_should_specific_value_given_exact_inputs() { - // Arrange - assert!(init(CurveType::BLS12_381)); - let coefficients = vec![1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13]; - let poly = Polynomial::from_i32(&coefficients); - // Act - let value = poly.eval_at(&Fr::from_int(17)); - // Assert - let expected = "39537218396363405614"; - let actual = value.get_str(10); - assert_eq!(expected, actual); -} - -#[test] -fn extend_poly_appends_fr_zero() { - // Arrange - assert!(init(CurveType::BLS12_381)); - let poly = Polynomial::from_i32(&[1, 2, 3, 4]); - // Act - let extended = poly.get_extended(8); - - // Assert - let expected = vec!["1", "2", "3", "4", "0", "0", "0", "0"]; - for (i, item) in expected.iter().enumerate().take(8) { - // for i in 0..8 { - assert_eq!(*item, extended.coeffs[i].get_str(10)); - } -} - -#[test] -fn poly_eval_0_check() { - //Arrange - assert!(init(CurveType::BLS12_381)); - let mut coefficients = Vec::new(); - let n: i32 = 7; - let a: i32 = 597; - - for i in 0..n { - coefficients.push(i + a); - } - let p = Polynomial::from_i32(&coefficients); - let expected = Fr::from_int(a); - - //Act - let actual = p.eval_at(&Fr::default()); - - //Assert - assert_eq!(expected, actual); -} - -fn get_test_vec(first: usize, second: usize) -> Vec { - // (x^2 - 1) / (x + 1) = x - 1 - let vec_0_0: Vec = vec![Fr::from_int(-1), Fr::from_int(0), Fr::from_int(1)]; - let vec_0_1: Vec = vec![Fr::from_int(1), Fr::from_int(1)]; - let vec_0_2: Vec = vec![Fr::from_int(-1), Fr::from_int(1)]; - - // (12x^3 - 11x^2 + 9x + 18) / (4x + 3) = 3x^2 - 5x + 6 - let vec_1_0: Vec = vec![ - Fr::from_int(18), - Fr::from_int(9), - Fr::from_int(-11), - Fr::from_int(12), - ]; - let vec_1_1: Vec = vec![Fr::from_int(3), Fr::from_int(4)]; - let vec_1_2: Vec = vec![Fr::from_int(6), Fr::from_int(-5), Fr::from_int(3)]; - - // (x + 1) / (x^2 - 1) = nil !!DOES NOT WORK WITH CURRENT IMPLEMENTATION OF METHOD - let vec_2_0: Vec = vec![Fr::from_int(1), Fr::from_int(1)]; - let vec_2_1: Vec = vec![Fr::from_int(-1), Fr::from_int(0), Fr::from_int(2)]; - let vec_2_2: Vec = vec![]; - - let data: [[Vec; 3]; 3] = [ - [vec_0_0, vec_0_1, vec_0_2], - [vec_1_0, vec_1_1, vec_1_2], - [vec_2_0, vec_2_1, vec_2_2], - ]; - - data[first][second].clone() -} - -#[test] -fn poly_test_long_division() { - assert!(init(CurveType::BLS12_381)); - const SIZE: usize = 2; //should be <= size of test data in get_test_vec() - - for i in 0..SIZE { - let first = get_test_vec(i, 0); - let second = get_test_vec(i, 1); - let third = get_test_vec(i, 2); - - let dividend = Polynomial::from_fr(first); - let expected = Polynomial::from_fr(third); - - let result = dividend.long_division(&second).unwrap(); - - let expected_len: usize = expected.coeffs.len(); - let result_len: usize = result.coeffs.len(); - - assert_eq!(expected_len, result_len); - for j in 1..result_len { - assert_eq!(result.coeffs[j], expected.coeffs[j]); - } - } -} - -/*Library could be improved to use status codes/Result or something like that, -since in current implementation it simply panics*/ -#[test] -fn poly_div_by_zero() { - //Arrange - assert!(init(CurveType::BLS12_381)); - let dividend_vec: Vec = vec![1, 1]; - let divisor: Vec = vec![Fr::default()]; - let dividend = Polynomial::from_i32(÷nd_vec); - - //Act - let dummy = dividend.long_division(&divisor); - - //Assert - assert!(dummy.is_err()); -} diff --git a/mcl/kzg-bench/src/shared_tests/bls12_381.rs b/mcl/kzg-bench/src/shared_tests/bls12_381.rs deleted file mode 100644 index 76696bc71..000000000 --- a/mcl/kzg-bench/src/shared_tests/bls12_381.rs +++ /dev/null @@ -1,138 +0,0 @@ -#[cfg(test)] -mod tests { - use kzg::common_utils::log_2_byte; - use kzg_bench::tests::bls12_381::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::data_types::g1::g1_linear_combination; - use rust_kzg_mcl::data_types::g1::G1; - use rust_kzg_mcl::data_types::g2::G2; - use rust_kzg_mcl::kzg10::Curve; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - pub fn log_2_byte_works_() { - assert!(init(CurveType::BLS12_381)); - log_2_byte_works(&log_2_byte); - } - - #[test] - pub fn fr_is_null_works_() { - assert!(init(CurveType::BLS12_381)); - fr_is_null_works::(); - } - - #[test] - pub fn fr_is_zero_works_() { - assert!(init(CurveType::BLS12_381)); - fr_is_zero_works::(); - } - - #[test] - pub fn fr_is_one_works_() { - assert!(init(CurveType::BLS12_381)); - fr_is_one_works::(); - } - - #[test] - pub fn fr_from_uint64_works_() { - assert!(init(CurveType::BLS12_381)); - fr_from_uint64_works::(); - } - - #[test] - pub fn fr_equal_works_() { - assert!(init(CurveType::BLS12_381)); - fr_equal_works::(); - } - - #[test] - pub fn fr_negate_works_() { - assert!(init(CurveType::BLS12_381)); - fr_negate_works::(); - } - - #[test] - pub fn fr_pow_works_() { - assert!(init(CurveType::BLS12_381)); - fr_pow_works::(); - } - - #[test] - pub fn fr_div_works_() { - assert!(init(CurveType::BLS12_381)); - fr_div_works::(); - } - - #[test] - pub fn fr_div_by_zero_() { - assert!(init(CurveType::BLS12_381)); - fr_div_by_zero::(); - } - - #[test] - pub fn fr_uint64s_roundtrip_() { - assert!(init(CurveType::BLS12_381)); - fr_uint64s_roundtrip::(); - } - - #[test] - pub fn p1_mul_works_() { - assert!(init(CurveType::BLS12_381)); - p1_mul_works::(); - } - - #[test] - pub fn p1_sub_works_() { - assert!(init(CurveType::BLS12_381)); - p1_sub_works::(); - } - - #[test] - pub fn p2_add_or_dbl_works_() { - assert!(init(CurveType::BLS12_381)); - p2_add_or_dbl_works::(); - } - - #[test] - pub fn p2_mul_works_() { - assert!(init(CurveType::BLS12_381)); - p2_mul_works::(); - } - - #[test] - pub fn p2_sub_works_() { - assert!(init(CurveType::BLS12_381)); - p2_sub_works::(); - } - - #[test] - pub fn g1_identity_is_infinity_() { - assert!(init(CurveType::BLS12_381)); - g1_identity_is_infinity::(); - } - - #[test] - pub fn g1_identity_is_identity_() { - assert!(init(CurveType::BLS12_381)); - g1_identity_is_identity::(); - } - - #[test] - pub fn g1_make_linear_combination_() { - assert!(init(CurveType::BLS12_381)); - g1_make_linear_combination::(&g1_linear_combination); - } - - #[test] - pub fn g1_random_linear_combination_() { - assert!(init(CurveType::BLS12_381)); - g1_random_linear_combination::(&g1_linear_combination); - } - - #[test] - pub fn pairings_work_() { - assert!(init(CurveType::BLS12_381)); - pairings_work::(&Curve::verify_pairing); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/consts.rs b/mcl/kzg-bench/src/shared_tests/consts.rs deleted file mode 100644 index 3bb44450b..000000000 --- a/mcl/kzg-bench/src/shared_tests/consts.rs +++ /dev/null @@ -1,53 +0,0 @@ -#[cfg(test)] -mod consts_tests { - use kzg_bench::tests::consts::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::fk20_fft::{ - expand_root_of_unity, init_globals, FFTSettings, SCALE_2_ROOT_OF_UNITY, - }; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - pub fn expand_root_of_unityarr(root: &Fr, _width: usize) -> Result, String> { - Ok(expand_root_of_unity(root)) - } - - #[test] - fn roots_of_unity_out_of_bounds_fails_() { - assert!(init(CurveType::BLS12_381)); - roots_of_unity_out_of_bounds_fails::(); - } - - #[test] - fn roots_of_unity_are_plausible_() { - assert!(init(CurveType::BLS12_381)); - - unsafe { - init_globals(); - let mut scale2_root_of_unity_arr: [[u64; 4]; 32] = [[0; 4]; 32]; - for i in 0..SCALE_2_ROOT_OF_UNITY.len() { - scale2_root_of_unity_arr[i] = SCALE_2_ROOT_OF_UNITY[i].to_u64_arr(); - } - roots_of_unity_are_plausible::(&scale2_root_of_unity_arr); - } - } - - #[test] - fn expand_roots_is_plausible_() { - assert!(init(CurveType::BLS12_381)); - unsafe { - init_globals(); - let mut scale2_root_of_unity_arr: [[u64; 4]; 32] = [[0; 4]; 32]; - for i in 0..SCALE_2_ROOT_OF_UNITY.len() { - scale2_root_of_unity_arr[i] = SCALE_2_ROOT_OF_UNITY[i].to_u64_arr(); - } - expand_roots_is_plausible::(&scale2_root_of_unity_arr, &expand_root_of_unityarr); - } - } - - #[test] - fn new_fft_settings_is_plausible_() { - assert!(init(CurveType::BLS12_381)); - new_fft_settings_is_plausible::(); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/das.rs b/mcl/kzg-bench/src/shared_tests/das.rs deleted file mode 100644 index 49f981fd1..000000000 --- a/mcl/kzg-bench/src/shared_tests/das.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[cfg(test)] -mod das_tests { - use kzg_bench::tests::das::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn das_extension_test_known_() { - assert!(init(CurveType::BLS12_381)); - das_extension_test_known::(); - } - - #[test] - fn das_extension_test_random_() { - assert!(init(CurveType::BLS12_381)); - das_extension_test_random::(); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/eip_4844.rs b/mcl/kzg-bench/src/shared_tests/eip_4844.rs deleted file mode 100644 index 36cc30192..000000000 --- a/mcl/kzg-bench/src/shared_tests/eip_4844.rs +++ /dev/null @@ -1,165 +0,0 @@ -#[cfg(test)] -mod tests { - use kzg_bench::tests::eip_4844::*; - use rust_kzg_mcl::data_types::{fr::Fr, g1::G1, g2::G2}; - use rust_kzg_mcl::eip_4844::*; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::kzg10::Polynomial; - use rust_kzg_mcl::kzg_settings::KZGSettings; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - pub fn bytes_to_bls_field_test_() { - assert!(init(CurveType::BLS12_381)); - bytes_to_bls_field_test::(); - } - - #[test] - pub fn compute_powers_test_() { - assert!(init(CurveType::BLS12_381)); - compute_powers_test::(&compute_powers); - } - - #[test] - pub fn blob_to_kzg_commitment_test_() { - assert!(init(CurveType::BLS12_381)); - blob_to_kzg_commitment_test::( - &load_trusted_setup, - &blob_to_kzg_commitment, - ); - } - - #[test] - pub fn compute_kzg_proof_test_() { - compute_kzg_proof_test::( - &load_trusted_setup, - &compute_kzg_proof, - &blob_to_polynomial, - &evaluate_polynomial_in_evaluation_form, - ); - } - - #[test] - pub fn compute_and_verify_kzg_proof_round_trip_test_() { - compute_and_verify_kzg_proof_round_trip_test::< - Fr, - G1, - G2, - Polynomial, - FFTSettings, - KZGSettings, - >( - &load_trusted_setup, - &blob_to_kzg_commitment, - &bytes_to_blob, - &compute_kzg_proof, - &blob_to_polynomial, - &evaluate_polynomial_in_evaluation_form, - &verify_kzg_proof, - ); - } - - //#[cfg(not(feature = "minimal-spec"))] - //#[test] - //pub fn compute_and_verify_kzg_proof_within_domain_test_() { - // compute_and_verify_kzg_proof_within_domain_test::< - // Fr, - // G1, - // G2, - // Polynomial, - // FFTSettings, - // KZGSettings, - // >( - // &load_trusted_setup, - // &blob_to_kzg_commitment, - // &bytes_to_blob, - // &compute_kzg_proof, - // &blob_to_polynomial, - // &evaluate_polynomial_in_evaluation_form, - // &verify_kzg_proof, - // ); - //} - - #[test] - pub fn compute_and_verify_kzg_proof_fails_with_incorrect_proof_test_() { - compute_and_verify_kzg_proof_fails_with_incorrect_proof_test::< - Fr, - G1, - G2, - Polynomial, - FFTSettings, - KZGSettings, - >( - &load_trusted_setup, - &blob_to_kzg_commitment, - &bytes_to_blob, - &compute_kzg_proof, - &blob_to_polynomial, - &evaluate_polynomial_in_evaluation_form, - &verify_kzg_proof, - ); - } - - #[test] - pub fn compute_and_verify_blob_kzg_proof_test_() { - assert!(init(CurveType::BLS12_381)); - compute_and_verify_blob_kzg_proof_test::( - &load_trusted_setup, - &blob_to_kzg_commitment, - &bytes_to_blob, - &compute_blob_kzg_proof, - &verify_blob_kzg_proof, - ); - } - - #[test] - pub fn compute_and_verify_blob_kzg_proof_fails_with_incorrect_proof_test_() { - assert!(init(CurveType::BLS12_381)); - compute_and_verify_blob_kzg_proof_fails_with_incorrect_proof_test::< - Fr, - G1, - G2, - Polynomial, - FFTSettings, - KZGSettings, - >( - &load_trusted_setup, - &blob_to_kzg_commitment, - &bytes_to_blob, - &compute_blob_kzg_proof, - &verify_blob_kzg_proof, - ); - } - - #[test] - pub fn verify_kzg_proof_batch_test_() { - assert!(init(CurveType::BLS12_381)); - verify_kzg_proof_batch_test::( - &load_trusted_setup, - &blob_to_kzg_commitment, - &bytes_to_blob, - &compute_blob_kzg_proof, - &verify_blob_kzg_proof_batch, - ); - } - - #[test] - pub fn verify_kzg_proof_batch_fails_with_incorrect_proof_test_() { - assert!(init(CurveType::BLS12_381)); - verify_kzg_proof_batch_fails_with_incorrect_proof_test::< - Fr, - G1, - G2, - Polynomial, - FFTSettings, - KZGSettings, - >( - &load_trusted_setup, - &blob_to_kzg_commitment, - &bytes_to_blob, - &compute_blob_kzg_proof, - &verify_blob_kzg_proof_batch, - ); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/fft_fr.rs b/mcl/kzg-bench/src/shared_tests/fft_fr.rs deleted file mode 100644 index f8c794f5d..000000000 --- a/mcl/kzg-bench/src/shared_tests/fft_fr.rs +++ /dev/null @@ -1,32 +0,0 @@ -#[cfg(test)] -mod fft_fr_tests { - use kzg_bench::tests::fft_fr::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn compare_sft_fft_() { - assert!(init(CurveType::BLS12_381)); - compare_sft_fft::(&FFTSettings::fft_fr_slow, &FFTSettings::fft_fr_fast); - } - - #[test] - fn roundtrip_fft_fr_() { - assert!(init(CurveType::BLS12_381)); - roundtrip_fft::(); - } - - #[test] - fn inverse_fft_fr_() { - assert!(init(CurveType::BLS12_381)); - inverse_fft::(); - } - - #[test] - fn stride_fft_fr_() { - assert!(init(CurveType::BLS12_381)); - stride_fft::(); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/fft_g1.rs b/mcl/kzg-bench/src/shared_tests/fft_g1.rs deleted file mode 100644 index 196e5ce83..000000000 --- a/mcl/kzg-bench/src/shared_tests/fft_g1.rs +++ /dev/null @@ -1,31 +0,0 @@ -#[cfg(test)] -mod fft_g1_tests { - use kzg_bench::tests::fft_g1::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::data_types::g1::G1; - use rust_kzg_mcl::fk20_fft::{make_data, FFTSettings}; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn roundtrip_fft_g1_() { - assert!(init(CurveType::BLS12_381)); - roundtrip_fft::(&make_data); - } - - #[test] - fn stride_fft_g1_() { - assert!(init(CurveType::BLS12_381)); - stride_fft::(&make_data); - } - - #[test] - fn compare_sft_fft_() { - assert!(init(CurveType::BLS12_381)); - compare_sft_fft::( - &FFTSettings::fft_g1_slow, - &FFTSettings::fft_g1_fast, - &make_data, - ); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/finite.rs b/mcl/kzg-bench/src/shared_tests/finite.rs deleted file mode 100644 index d4059b9ea..000000000 --- a/mcl/kzg-bench/src/shared_tests/finite.rs +++ /dev/null @@ -1,13 +0,0 @@ -#[cfg(test)] -mod finite_test { - use kzg_bench::tests::finite::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn sum_of_two_zeros_is_zero_() { - assert!(init(CurveType::BLS12_381)); - sum_of_two_zeros_is_zero::() - } -} diff --git a/mcl/kzg-bench/src/shared_tests/fk20_proofs.rs b/mcl/kzg-bench/src/shared_tests/fk20_proofs.rs deleted file mode 100644 index 094ecd479..000000000 --- a/mcl/kzg-bench/src/shared_tests/fk20_proofs.rs +++ /dev/null @@ -1,59 +0,0 @@ -#[cfg(test)] -mod tests { - use kzg_bench::tests::fk20_proofs::*; - use rust_kzg_mcl::data_types::{fr::Fr, g1::G1, g2::G2}; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::fk20_matrix::{FK20Matrix, FK20SingleMatrix}; - use rust_kzg_mcl::kzg10::Polynomial; - use rust_kzg_mcl::kzg_settings::KZGSettings; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn test_fk_single() { - assert!(init(CurveType::BLS12_381)); - fk_single::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn test_fk_single_strided() { - assert!(init(CurveType::BLS12_381)); - fk_single_strided::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn test_fk_multi_settings() { - assert!(init(CurveType::BLS12_381)); - fk_multi_settings::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn test_fk_multi_chunk_len_1_512() { - assert!(init(CurveType::BLS12_381)); - fk_multi_chunk_len_1_512::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn test_fk_multi_chunk_len_16_512() { - assert!(init(CurveType::BLS12_381)); - fk_multi_chunk_len_16_512::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn test_fk_multi_chunk_len_16_16() { - assert!(init(CurveType::BLS12_381)); - fk_multi_chunk_len_16_16::( - &KZGSettings::generate_trusted_setup, - ); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/kzg_proofs.rs b/mcl/kzg-bench/src/shared_tests/kzg_proofs.rs deleted file mode 100644 index e4f46fa26..000000000 --- a/mcl/kzg-bench/src/shared_tests/kzg_proofs.rs +++ /dev/null @@ -1,42 +0,0 @@ -#[cfg(test)] -mod kzg_proofs_tests { - use kzg_bench::tests::kzg_proofs::*; - use rust_kzg_mcl::data_types::{fr::Fr, g1::G1, g2::G2}; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::kzg10::Polynomial; - use rust_kzg_mcl::kzg_settings::KZGSettings; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn proof_single_() { - assert!(init(CurveType::BLS12_381)); - proof_single::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn commit_to_nil_poly_() { - assert!(init(CurveType::BLS12_381)); - commit_to_nil_poly::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn commit_to_too_long_poly_returns_err_() { - assert!(init(CurveType::BLS12_381)); - commit_to_too_long_poly_returns_err::( - &KZGSettings::generate_trusted_setup, - ); - } - - #[test] - fn proof_multi_() { - assert!(init(CurveType::BLS12_381)); - proof_multi::( - &KZGSettings::generate_trusted_setup, - ); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/poly.rs b/mcl/kzg-bench/src/shared_tests/poly.rs deleted file mode 100644 index 877d16bdf..000000000 --- a/mcl/kzg-bench/src/shared_tests/poly.rs +++ /dev/null @@ -1,93 +0,0 @@ -#[cfg(test)] -mod poly_tests { - use kzg_bench::tests::poly::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::kzg10::Polynomial; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn create_poly_of_length_ten_() { - assert!(init(CurveType::BLS12_381)); - create_poly_of_length_ten::(); - } - - #[test] - fn poly_eval_check_() { - assert!(init(CurveType::BLS12_381)); - poly_eval_check::(); - } - - #[test] - fn poly_eval_0_check_() { - assert!(init(CurveType::BLS12_381)); - poly_eval_0_check::(); - } - - #[test] - fn poly_eval_nil_check_() { - assert!(init(CurveType::BLS12_381)); - poly_eval_nil_check::(); - } - - #[test] - fn poly_inverse_simple_0_() { - assert!(init(CurveType::BLS12_381)); - poly_inverse_simple_0::(); - } - - #[test] - fn poly_inverse_simple_1_() { - assert!(init(CurveType::BLS12_381)); - poly_inverse_simple_1::(); - } - - #[test] - fn poly_mul_direct_test_() { - assert!(init(CurveType::BLS12_381)); - poly_mul_direct_test::(); - } - - #[test] - fn poly_test_div_() { - assert!(init(CurveType::BLS12_381)); - poly_test_div::(); - } - - #[test] - fn poly_div_by_zero_() { - assert!(init(CurveType::BLS12_381)); - poly_div_by_zero::(); - } - - #[test] - fn poly_mul_fft_test_() { - assert!(init(CurveType::BLS12_381)); - poly_mul_fft_test::(); - } - - #[test] - fn poly_mul_random_() { - assert!(init(CurveType::BLS12_381)); - poly_mul_random::(); - } - - #[test] - fn poly_div_random_() { - assert!(init(CurveType::BLS12_381)); - poly_div_random::(); - } - - #[test] - fn poly_div_long_test_() { - assert!(init(CurveType::BLS12_381)); - poly_div_long_test::(); - } - - #[test] - fn poly_div_fast_test_() { - assert!(init(CurveType::BLS12_381)); - poly_div_fast_test::(); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/recover.rs b/mcl/kzg-bench/src/shared_tests/recover.rs deleted file mode 100644 index 10c6d4578..000000000 --- a/mcl/kzg-bench/src/shared_tests/recover.rs +++ /dev/null @@ -1,27 +0,0 @@ -#[cfg(test)] -mod recover_tests { - use kzg_bench::tests::recover::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::kzg10::Polynomial; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn recover_simple_() { - assert!(init(CurveType::BLS12_381)); - recover_simple::(); - } - - #[test] - fn recover_random_() { - assert!(init(CurveType::BLS12_381)); - recover_random::(); - } - - #[test] - fn more_than_half_missing_() { - assert!(init(CurveType::BLS12_381)); - more_than_half_missing::(); - } -} diff --git a/mcl/kzg-bench/src/shared_tests/zero_poly.rs b/mcl/kzg-bench/src/shared_tests/zero_poly.rs deleted file mode 100644 index 4b0cdba76..000000000 --- a/mcl/kzg-bench/src/shared_tests/zero_poly.rs +++ /dev/null @@ -1,51 +0,0 @@ -#[cfg(test)] -mod zero_poly_tests { - use kzg_bench::tests::zero_poly::*; - use rust_kzg_mcl::data_types::fr::Fr; - use rust_kzg_mcl::fk20_fft::FFTSettings; - use rust_kzg_mcl::kzg10::Polynomial; - use rust_kzg_mcl::mcl_methods::init; - use rust_kzg_mcl::CurveType; - - #[test] - fn test_reduce_partials_() { - assert!(init(CurveType::BLS12_381)); - test_reduce_partials::(); - } - - #[test] - fn reduce_partials_random_() { - assert!(init(CurveType::BLS12_381)); - reduce_partials_random::(); - } - - #[test] - fn check_test_data_() { - assert!(init(CurveType::BLS12_381)); - check_test_data::(); - } - - #[test] - fn zero_poly_known_() { - assert!(init(CurveType::BLS12_381)); - zero_poly_known::(); - } - - #[test] - fn zero_poly_random_() { - assert!(init(CurveType::BLS12_381)); - zero_poly_random::(); - } - - #[test] - fn zero_poly_all_but_one_() { - assert!(init(CurveType::BLS12_381)); - zero_poly_all_but_one::(); - } - - #[test] - fn zero_poly_252_() { - assert!(init(CurveType::BLS12_381)); - zero_poly_252::(); - } -} diff --git a/mcl/kzg-bench/src/test.rs b/mcl/kzg-bench/src/test.rs deleted file mode 100644 index cafc9aad0..000000000 --- a/mcl/kzg-bench/src/test.rs +++ /dev/null @@ -1,583 +0,0 @@ -// use std::{mem, vec}; -use rust_kzg_mcl::mcl_methods::*; -use std::mem; -// use rust_kzg_mcl::utilities::*; -// use rust_kzg_mcl::kzg10::*; -use rust_kzg_mcl::data_types::{fp::*, fp2::*, fr::*, g1::*, g2::*, gt::*}; -use rust_kzg_mcl::CurveType; -// use rust_kzg_mcl::fk20_fft::*; -// use rust_kzg_mcl::fk20_matrix::*; - -#[test] -#[allow(clippy::many_single_char_names)] -fn mcl_test() { - assert_eq!(mem::size_of::(), 32); - assert_eq!(mem::size_of::(), 48); - assert_eq!(mem::size_of::(), 48 * 2); - assert_eq!(mem::size_of::(), 48 * 3); - assert_eq!(mem::size_of::(), 48 * 2 * 3); - assert_eq!(mem::size_of::(), 48 * 12); - assert!(init(CurveType::BLS12_381)); - assert_eq!(get_fp_serialized_size(), 48); - assert_eq!(get_g1_serialized_size(), 48); - assert_eq!(get_g2_serialized_size(), 48 * 2); - assert_eq!(get_gt_serialized_size(), 48 * 12); - assert_eq!(get_fr_serialized_size(), 32); - - // Fp - assert_eq!(get_field_order(), "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787"); - // Fr - assert_eq!( - get_curve_order(), - "52435875175126190479447740508185965837690552500527637822603658699938581184513" - ); - - field_test! {Fr}; - field_test! {Fp}; - - let p = G1::from_str("1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569", 10).unwrap(); - let q = G2::from_str("1 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582", 10).unwrap(); - - ec_test! {G1, Fp, p}; - ec_test! {G2, Fp2, q}; - - let x = Fr::from_int(3); - let y = Fp::from_int(-1); - let mut e = GT::zero(); - pairing(&mut e, &p, &q); - serialize_test! {Fr, x}; - serialize_test! {Fp, y}; - serialize_test! {G1, p}; - serialize_test! {G2, q}; - serialize_test! {GT, e}; -} - -// const GEN_G1_STR: &str = "1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569"; -// const GEN_G2_STR: &str = "1 352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160 3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758 1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905 927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582"; -// #[test] -// fn curve_new_sets_g1_gen_to_correct_val() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// // Act -// let curve = Curve::new(&Fr::one(), 1); -// // Assert -// let result = curve.g1_gen.get_str(10); -// assert_eq!(GEN_G1_STR, result); -// } - -// #[test] -// fn curve_new_sets_g2_gen_to_correct_val() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// // Act -// let curve = Curve::new(&Fr::one(), 1); -// // Assert -// let result = curve.g2_gen.get_str(10); -// assert_eq!(GEN_G2_STR, result); -// } - -// #[test] -// fn curve_new_first_g1_point_is_generator() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// // Act -// let curve = Curve::new(&Fr::one(), 1); -// // Assert -// let result = curve.g1_points[0].get_str(10); -// assert_eq!(GEN_G1_STR, result); -// } - -// #[test] -// fn curve_new_first_g2_point_is_generator() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// // Act -// let curve = Curve::new(&Fr::one(), 1); -// // Assert -// let result = curve.g2_points[0].get_str(10); -// assert_eq!(GEN_G2_STR, result); -// } - -// #[test] -// fn curve_new_g1_points_should_have_exact_values_given_specific_params() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let secret = Fr::from_str("1927409816240961209460912649124", 10); -// // Act -// let curve = Curve::new(&secret.unwrap(), 17); - -// // Assert -// let strs: Vec = curve.g1_points.iter().map(|x| x.get_str(10)).collect(); - -// let expected = [ -// "1 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569", -// "1 2152869591689196284448695346189574884812111481958382828258011215851576980696076283357586937048281406709538669668556 1837985193201176164563363095685788695060722952730414729513827449189998486108746221085867464994192483925080285065018", -// "1 3262605383935052083682746418410148264888435523851787883646428634651057127775051437848295094756022375626344454529853 170376908770402617588871716106905630704800483257535202301637743269417617389615424187202633271003852068580182760145", -// "1 880220465676249036392707021793508724521687313339128521628378026681982232143465812471317982023333854734330480948673 2902223523920951554723894475268175106169924753723683323415827815697283974835754478310015241899366201222645054649608", -// "1 3244388122438103216409647202891415823727015100716970678191779835123826603745878948836800400002635659162267031975583 1585253991742417487161783435845975575940496801371133300360989731905095816244520655199543596433385055483512833757601", -// "1 1691444095738545636838570153348610026182961225323356293730618623455617099056679194783075235346140714244554956873033 961647227525848937006956574637866372979536342809091069926681629924395961591459720348224030656076442822973218085550", -// "1 3577901166225087165094130311167725910816358129621364033783794190115179171035326630844229271546155259801088983862479 3092642789043285621253509221940543294037789204421586765911962911994791146080221763753835525158184924558752020565291", -// "1 3013186384424179439775834119326464143135586883979982227880894049363998889225981543565484795480442461763905556101762 2478178060772079991661592547244530979985617852562178845899785854640900915922275633937010001028451411707598232298832", -// "1 2399231498671876712809138864159907535047647996068498551664715372729570379868491143868576593216337700083434635379685 482713507023481840088214347482905793358357894612071198190992625150626572379700355268448916577827133516290766497622", -// "1 3969977694904317593192991000252371163313871217135365989839005125424170023895776071038962785493744895844713942612974 4413699249467038796028960432613629427107969427001375982715766204951543003390119367884220008325083276852454909781", -// "1 194075085492710730179274360855839046245139911409378180773739622831795665144267111066969149760214641537576331892106 2829985443790966823527351173358032012294116269530327251028202388989851835102944896169897747047401344807088160112615", -// "1 3280685826964465549968732412388399530552593104925613549928682916052288843943420728109800551779100636680533358924443 298681365483796231406540809779630027096164486961762590101806824599619177657034359801891143498721811778563760637265", -// "1 3400935219571983529219239890354858045697412824966239298938573345769483174728220352364464899823354648929772679742552 191348415359823743448098111145821414668135484237623052156975028197191932451915485624239658088947171507703851149457", -// "1 3374538774097525861555904858666250834790705983053158676667960471408213151238217454016543185985604089823231022873495 3258515632833107359343766033193307526227113423713039039660926225561152436287447196511646604996224783556594615862297", -// "1 84257718831135536599708664101759228548259087509946180939819270114426033813393924094069423610123184508861693807222 1425072665498715675588703937845375337020452759807133251766395540291673980878175955156843196123520432067102459055363", -// "1 3252002729706195882623612396123269947851274285378019889513328537606104266375911074185178476483143881219657281907365 2744825182574836694639045426047274581117055175119425124924870369929899567807025339868314937727954579104158715615767", -// "1 3105530220482690203381088120196667002396187280376878591204985144810501655541159693720070013410365841734894244215545 2515128161348588248190794853040865399542397670879510720694265058064715843238549344693260209850633864871507776822678" -// ]; - -// assert_eq!(expected.len(), strs.len()); -// let all_values_equal = expected.iter().zip(strs.iter()).all(|(a, b)| a == b); -// assert!(all_values_equal); -// } - -// #[test] -// fn polynomial_generate_proof_at_should_have_a_specific_value_given_exact_inputs() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let coefficients = vec![1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13]; -// let poly = Polynomial::from_i32(&coefficients); -// let secret = Fr::from_str("1927409816240961209460912649124", 10); -// let curve = Curve::new(&secret.unwrap(), poly.order()); - -// let point = Fr::from_int(17); -// // Act -// let proof = poly.gen_proof_at(&curve.g1_points, &point); -// // Assert -// let expected = "1 867803339007397142967426903694725732786398875082812714585913536387867789215930966591756718433944432919654354450045 1056604647851765547809696011101405958529416282518275445556537937608095695960215709670255078026676619389223749112525"; -// let actual = proof.get_str(10); -// assert_eq!(expected, actual); -// } - -// #[test] -// fn polynomial_commit_should_have_specific_value_given_exact_inputs() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let coefficients = vec![1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13]; -// let poly = Polynomial::from_i32(&coefficients); -// let secret = Fr::from_str("1927409816240961209460912649124", 10); -// let curve = Curve::new(&secret.unwrap(), poly.order()); -// // Act -// let commitment = poly.commit(&curve.g1_points); -// // Assert -// let expected = "1 2477800657478396280496910737712311876776119382023479023481824166251818861301026600704438635866253640104679377733301 2954229993619572531997767690230550003591055333364019243777247691138518393343620011708288769387987906907914339131963"; -// let actual = commitment.get_str(10); -// assert_eq!(expected, actual); -// } - -// // #[test] -// // fn curve_is_proof_valid_should_return_true_when_same_parameters_used_for_gen_are_passed() { -// // // Arrange -// // assert!(init(CurveType::BLS12_381)); -// // let coefficients = vec![1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13]; -// // let poly = Polynomial::from_i32(&coefficients); -// // let secret = Fr::from_str("1927409816240961209460912649124", 10); -// // let curve = Curve::new(&secret.unwrap(), poly.order()); -// // let x = Fr::from_int(17); -// // let y = poly.eval_at(&x); -// // let proof = poly.gen_proof_at(&curve.g1_points, &x); -// // let commitment = poly.commit(&curve.g1_points); - -// // // Act -// // let is_valid = curve.is_proof_valid(&commitment, &proof, &x, &y); - -// // // Assert -// // assert!(is_valid); -// // } - -// #[test] -// fn proof_loop_works_with_random_points() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let coefficients = vec![1, 2, 3, 4, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13]; -// let poly = Polynomial::from_i32(&coefficients); -// let secret = Fr::from_str("1927409816240961209460912649124", 10); -// let curve = Curve::new(&secret.unwrap(), poly.order()); -// let mut x = Fr::default(); -// x.set_by_csprng(); -// let y = poly.eval_at(&x); -// let proof = poly.gen_proof_at(&curve.g1_points, &x); -// let commitment = poly.commit(&curve.g1_points); - -// // Act -// let is_valid = curve.is_proof_valid(&commitment, &proof, &x, &y); - -// // Assert -// assert!(is_valid); -// } - -// // FFT | FK20 - -// #[test] -// fn fk20matrix_new_builds_valid_settings() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let chunk_len: usize = 16; -// let chunk_count: usize = 32; -// let n = chunk_len * chunk_count; -// let secret = Fr::from_str("1927409816240961209460912649124", 10).unwrap(); -// let kzg_curve = Curve::new(&secret, n * 2); - -// // Act -// let _matrix = FK20Matrix::new(kzg_curve, n * 2, chunk_len, 10); - -// // Assert -// // Correctness can be implied from first few values (16 in this case), they should already fail if the math is wrong - -// let expected = vec! [ -// vec![ -// "1 2690832516741773119369730195519233968670522532392277474918267333033611475380645539270351007440482196987183887535296 3175213108544898085235166650679988026781072495712618074575168602254234390929160150851454512872056164806990780792922", -// "1 2072581413858441891826784938377829697673783610659410996308538512601613765043399095800516290404055589595125799432122 142040439119123504001234579304338655335210122734240515030365715479774071518630496001621684305521225040450706348551", -// "1 555010171546632414521023935674583992733334771853376894411915581475492990139012758601221152458226727016075286216242 2062479129870967993306760396974811168673763387664849025697582237771721030661986154982695543533682664546516347371968", -// "1 3274267611093990689706613371114507668087156239339065210265274210658495136561870064066396901301804354860098305637773 1241367983506779525903776542849574539651055454935231205394295862302812863367013952476859950248432249611367763641340" -// ], -// vec![ -// "1 81522731869730999016959108083541803120177810361736504886071026273980013178149605563448968405343219016356457377406 223274507986138220257689974122380902783145216603518153965998726451791348801627930908125076444038423438559369671335", -// "1 3808464147164295345562978721284821594881637392419762556251712176551059711254755949783485066757083577643300339738721 2337549690718040172853841991558609929010921665385090242504524831444799802230084391557597182183378960598988157802881", -// "1 1661106895620331931115890729226506793498011737553071873254899785190234378452033779328593622276377978000761133037174 2445347359869286892162840464558476532632011042616786499244072070198386047563170774354968963497330110714438435368937", -// "1 726908696109837797869899134069048163881394782609717052922719680227299711126127802782293660508110445479794886391401 187298544861488465989428414398245070629614927536653835940256772000120459492183965098569970036249145900702528979827" -// ], -// vec![ -// "1 3929179374960622172469324744576568313316341672612295875559925412502214813185246547462214191845133455654404464431034 177314913203158567442861000406323035228440243612857286237333697289368056582084667990049976226354155824278044028426", -// "1 2810866607762757510487238314227157563656118171761037767974389692498157494265088725741234636840180283484125764176526 1153340612075592623161861036254693462133315972889763901198162727295011215538060079719205772192574089536241444413835", -// "1 2352507531104726620898783532555364575782896024235836241392390863453154114636517685772562779410947050627812034072696 331974667649324341661653091834745820547065903394704077483844952289903755698654916183305775816301208642629324471541", -// "1 2957732685660581771925637615807550148325705520173275796227684635236124841259383250952421665771963820726076493196248 338553886723949572883804365524830562024026898652359650933083054801490785805523765168050975042270646485897644019017" -// ], -// vec![ -// "1 3436597092609499366310156490230285384204497124660023916476036969277149477335171650302251387977464315802038218054432 1013543446377923239229961246336359501594126239606195398173820625012770253827026398483791670086988400847612228427838", -// "1 1409052333937843415498761271262190356511721853350750319265371330255898309407438908370572807856827206959888511441367 3596468817253648457210601545007261268736681745416046300717714875685865557954316628580965013164962441617400335917668", -// "1 1025004965225058732445243741231944317494892072556798478905167726638397386436922188895144678987782142961770271023278 207421088022499784706717350268057238112320710669626250564329439615036440987208898297017341060271480322006449501306", -// "1 173056978640834285267728646360319198265311839401954061920970102546631676339475037629314948445833468137008003754256 431688197610227819993661736708924947195077534539500276871543225713960859228823234674470547057839182178354038654930" -// ] -// ]; - -// for (_i, item) in expected.iter().enumerate().take(4) { -// for (j, item2) in item.iter().enumerate().take(4) { -// let str = *item2; -// assert_eq!(item[j], str); -// } -// } -// } - -// #[test] -// fn get_next_power_of_two_returns_correct_values() { -// // Arrange -// let xs: Vec = vec![ -// 2, -// 4, -// 5, -// 15, -// 16, -// 32, -// 64, -// 63, -// 122, -// 250, -// 510, -// 1023 -// ]; - -// // Act -// let x_next_pows: Vec = xs.iter().map(|x| next_pow_of_2(*x)).collect(); - -// // Assert -// let expected = [ -// 2, 4, 8, 16, 16, 32, 64, 64, 128, 256, 512, 1024 -// ]; - -// fn assert_eq_ints(a: i32, b: i32){ -// assert_eq!(a, b); -// } - -// expected.iter().zip(x_next_pows) -// .for_each(|(a, b)| assert_eq_ints(*a, b as i32)); - -// } - -// #[test] -// fn dau_using_fk20_multi_generates_exact_values_given_known_inputs() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let chunk_len: usize = 16; -// let chunk_count: usize = 32; -// let n = chunk_len * chunk_count; -// let secret = Fr::from_str("1927409816240961209460912649124", 10).unwrap(); -// let kzg_curve = Curve::new(&secret, n * 2); -// let matrix = FK20Matrix::new(kzg_curve, n * 2, chunk_len, 10); -// let polynomial = build_protolambda_poly(chunk_count, chunk_len, n); -// // Act -// let proofs = matrix.dau_using_fk20_multi(&polynomial); -// // Assert - -// let expected = vec![ -// "1 3049109670073243942711931801211551991977350609702786082875404381705054902889931096164119150944119739492900124336718 3803822584037975486135926890961136037182668503033554406702973802744799509630262359817965611370864159333294931292175", -// "1 658235374988622731991675177666095672656291387756593365624244986468346518201077057409039732423968458648837994174735 170658666960408025187423476299064494998912902640258589264830794057063295972343916527776401279871390447819757126953", -// "1 1130030307519988448139295049461510689137443815100405310480493976965267608972045460391887929059913107097949172071274 911288853670895051259117233708763590036202015720787567004896457725130794934681239923678442140285678050983038168299", -// "1 184629118130529419871030999265232663307951402211197098658674455562882083362295674399013655540875894788946477322610 151018441635394393779487005537260697520712932400843464500846745577910710608660322436531885388001200325206726382822", -// "1 2965006218588171911839741411579274455192644911372149980469646566392972074663902475612733690733254541596653454904283 3275738345360711133832726174651771742395571354143432726706954907416467801246321209431055071215896484783596433736625", -// "1 226211830732636399272913016291435289544236146253455171901132449681440440839680815281702922957676848869329764403133 1273222136784997093826876677486067241072759795029899813936082514685504740947934866532015493634821844030819498076895", -// "1 1149776898582874828633842575343212404812094446145240314401748679472982280041452329353170311910023385405387674593276 1637952245507884813137885602336915093444400294864264642575791181396421113346001095622637722830079603538054013394481", -// "1 3671406965382067478983181087394873895813113690618430410099472132018382932494462848773457060525727488613956237916770 3829765176925790120473358320055012101543579078175421537101525542306214004152149593326072127663015004822032541535514", -// "1 2137434617919227137680124479623931713314737491185201745657630847252644069932385393878386176935271178312938010988692 2595433768146635676027788672937803502296632112218901299679018639313969094973844203166883184573651103390568085801542", -// "1 2893208070843873309277321317652051436230408247670151173409515920482259208546916900748192556806181729564122818295148 459804412367023637651729293569664426246110838079127464241516501632883738002529280922732217507791898316821239797873", -// "1 3205923980234644099221737743072317320063919320208377144490385357295490471644091537059418297831954929118386763523038 1288504508929959814414158800774383293256835476780341192971534799032406685703092780038084702655967032933028428945098", -// "1 3225174118951822648584497923696240381542020657090095855020271969865693280449469772322072433428230107858611451485445 433992622026347280933529124004431262011884268032675432069826449404693982233636064330755751053333657937864816444877", -// "1 2853782113129612133795837641193144604035620064578392188628559737847614194133441123745427605136128138635178897496002 806137158560414045196489349283568294612997342547684959629733953942191073627534913977997288935060367318134284243339", -// "1 369973130057525845989015185664311486557821737062180001473059796142226562693448212290989708215386553356446897734103 1182124007588358644663978802314385537788779267209014363985652807033438634600830249367699699541525485237656325113819", -// "1 2264571844781141959191779082490912645128683845271352908867933224387329888642704803701608897486932142183607568614052 1028215621763961025128743424439709026502978589810138918517875913737272123626185774864840714501605279512293826481651", -// "1 2736796969582277298046221237579106469241080875733710339086583219851850933444141885926466467584972544565785782295125 2355152503823994882114160820860379167854113619454271503730927433225296043851468473219480354129014614931941930849576", -// "1 1168390407886734887717966303111231278719570305182204694317239720869809166090743330980039486527976335091089216648778 1934769259338575890701363612119485940635687151940592140345541909524549943682524790737060962484243564997095247232597", -// "1 3252759351667653266470679048886421374131770288372637583331028528874761138417717777972725688672181742494918320232197 24342955530195236963041786259374011817266321019638174000860813936891099695670800249546705818989754841531701159199", -// "1 2180644859325969809531199058330182983311912424542075500243193977938444608379328335962032916475177414228522715196986 531481339653002742605615041773733589604381196761630888823346991134350271146840998999051858297727170588353043393454", -// "1 3816593091473350513700679790876022359154900407339315734093887653792948324157436596675446721382472759529837736267233 1981421425169983417632200190282195796450663660579938985718145570868340670967760415281115509294180261116548333651680", -// "1 302897050875298705703283981596996991015612011694440401556683146767088218705270010796962116018944148757674812495839 2170665093489390599160241404048224124812861408473929366096485634292898811383949948942709140700119096523267010521716", -// "1 1704091680632916920339057420329420385648782751299879359007384363962120643496465008654151695685874927309675200002800 3984291653652699653065701427817239744202179650424363211696148443449860491396089551367527622898921941022046820789468", -// "1 261778742290110140366076531798732132033197983737582754757082866939691516459023694651214432940933331007050524667091 1424049893034598632045905011237129938497646238436427939687897713412736615989753077945464536842492952258704192781415", -// "1 3014938822530517707612563854568326963731081193994879617444224583283187323265083743364165173201909610206052912041288 2643216766554474849347794880006777726435696409265041443759799011352785142583303751098496135983555310522287392482015", -// "1 2953027679209148532521241459634984086536857016943499308491406213978216521716559735507366098092985987297862584558981 1492449947535208338231259441844857908576708279413481753338372917119481299939870186903185286297278020437233411208234", -// "1 616980473529098999393427231387709801230214960036443392464416095933330644067328036425843208491478657821030999384322 1603255868870050243428889675607333038651071386156094929881055026116715204759385216167080777635575028041532215734402", -// "1 2524653663673463103965440962912888444071376533252025941428734913603758455281716449003825412513812303128880754949381 2639496572521639559328406132445709180692953505915875210226717841842067742348275225496935566371233160274949954755250", -// "1 591201233666441000647964802791191434921597667798306675020399956529377713817853650746206610327279646873311461394337 396095043193100021559225292969991035010259567365047746600110797201107151857944961241452591537857312230235898173550", -// "1 2209841347337504027298746232150472396812720101984759689612173256094097998142512037358502565733255699012621861091228 217248284934454074657446489350527503217952916770877058681292976415195994228420003633307742264276831791371522399577", -// "1 2033320011776628583869744439428308624738531272318395551598286257417844744926132625231658065422648778457570427848476 3795771036318493474673600438303901230565877236832396230613562603152206815109547479438698538405892536910781059689239", -// "1 1006474202722518854241793437158456116697497354868758296437055826177113576674090074489625764858501388062161281184950 3328721796166965045488739611778325237957580879022654727614943976303518110709162253442422673693183301387551242930934", -// "1 2436291363234584225951005116304939754967140799844304050431093694593461216772003580114980903190440331543153256487404 1944025990085753677033121004443654841655870548652994070751291129324492783280023180223826394983675459612530868915495", -// "1 488012660445297837065946940671394449208592861195365968172276642060104464475817817444379281474659601425087432033419 880218684309236660402853631172467802196042915277918055509847437340208325785226920166019363686359735795512379386031", -// "1 1428409243996059198034861091971475761418325098430284194948255537037085544210315692681384336906833983021823957384555 1424753930018125406824056283882283821957897940861739865375641876759439482977488517588620744625249905936341076122039", -// "1 3254502238335214814517554609420815060691880314226955570204270018194705270213129991093354373792879751997722702136366 1478391668875851113543724582347596168545948046581865243981838765674654373836535371591064475092075271185219531884449", -// "1 3217553929272096993601888287069884082531320522675211803786016653197375828447441580428842603912278983474169428652748 3379802546638432084724440636803312434088003748109397909184114409380001422110195432477148280521029806034283975531837", -// "1 3788089332853432938766799277673725457064873731929638344041513934783613242371698993391408484167153716396460036805205 938511051923663772539776516116224544136719372492254208026134051389595698671182136489979549576523680152324202029009", -// "1 1247704474523120779168931167401307018184573242213527649887824359720997600834936197321437044109782492256145636339702 1448553523747097143337783292809862537588401487738055277488929560725744850887287214010204283066549226431174113973889", -// "1 1127429186036602308780522608934999868687921585498052211404016967025448367775052214631363626470530922574686883692460 672408927337644490222875125522136916312191926264177044153357488322547901946138486770383469468782496008159876672019", -// "1 2086690109632642272447870337065028103961540784690857457316307162356818597383568234110019969194182271552145764152441 1955979794589392233724318999037480128719699812490139625417735857404526615660420349931222133500045127011614435159865", -// "1 1938815620108164567180955402638031423826316271716510316691301979241466547544303760042696614690828331082214593352726 3956595416366239260474879295307289794795772192526485079081484657758264073298189594324146389255835241581613990208164", -// "1 3151889862435366742501016923612278296892979709397274125585369365004610832839522196951673479966542950606612731680743 3553588475575294242016341047111146014917838200398037130981550362939257973609302823426956775691042564923992423492655", -// "1 849573021684532446999967933992839525261344460767154253453431806818530393923752290964662775625688105076989209888985 190011245662137907909256860812306901877485802350986421502079643920280574106940641014873203560626150634878596496836", -// "1 864243516748681474717236495977930140680933400819591435652335059547949437841040276200083849458249836353553630749854 984807954653274671803283773627966584136032108108658306339902858177683643828845573586090007203626153690317032417540", -// "1 2494542486243118620059532492891175994518742657079260134752700613247754605508262095733956907483479380709902905033842 3658888642376338417254020186731758610636164227862354835081371641512635881145780734795272913541427585074350219015721", -// "1 264132726799810243189350587670745048920154713369306161293286151494576162781844464620298105008256034856490484057320 1042899353803691606000261482908466711114137377107787795618380568300915216740525308647083258614943723332196171057287", -// "1 429097533359462718070366403668675932578278552070922010146217719315934244077233613438196824414420018191713983494865 3059733090430070418361659068220140231519799336569956580087342284380943109170775208264795631655567728140277545717465", -// "1 2624454966557978652365578738379795641328990838424934007080853511017453783778500771424012996056221545154138539603491 388145349704142670716717791003683429709579585763674924641984565422268747707759828315299352352755767679109570538723", -// "1 2330557824108149292765308298800373839736370637461799609828805507923826370501362137184416307190818396528071666763554 761698249139677985779676078183692810628068887131496081380141956910869639393360620706422152273420173856593615873989", -// "1 2260826233449488990871758739890499511318172033523864279777819457164905555960336645122484916267837754700617905554691 3586388074591443866194754783149037319353483564214652533348633255755748973551444855882207876438617492636202166744025", -// "1 2645823359123880746590774878804249059682099875827840160419087159626304315120696625819894618626323445297411738288015 3523444762676563524480442965995210123003337033213575291323892038736745129932637446059011036862847735317998427087754", -// "1 3506937036895095073657547529563342349609873909322255567927773026448969712178158320213067175021494473189763593835798 518508850306909802863884353275302217996944580834347753302651780191445761521456253277360714873602554862298375902256", -// "1 3574612772404738832800943764796542675865441044711406850119038358608695059056389276895053341293269562047387509133568 2472281453911274486120884749992344304658829510662021670785271838275518121350284489992410388677761399725507918289745", -// "1 151013110218353564639946679308762520933930490939195383288451782134580721467650501972867339739296578602979277267074 3265104433752729946220284548715719694818421613722315589583569463003045872578897937002238490806536235554280060887088", -// "1 3758383139120564219509059314479582962173782602454558891526576858576474553908857057426352812162220348117828702420906 2870118308659054666896648400526066440559023518009797194689746393735228862993974889532753117292823557783819096061277", -// "1 690005440500710402693504132900670871221537986532478208044604643573196011621043953129585699894032300240346473547685 1170629884697634637922728816184368752643287923137165179608903004422976094574955608954074214418545122955256241898152", -// "1 1602634746217777688978746688922149627191904410631337330976847479235055040444628564987496583169322237383671539597477 2401142629933182803129123159610149066707120037920240426411140969961610467103947475652921088520771413782962008511286", -// "1 949903287489545585636612346848188825969331515152905139508887072183231919553574003972007136336504659716678058206911 3006744017035726759407700294475023340459058782231221593375643095628937552108837425922284831084517678663883436415632", -// "1 552257874025534510327816741956209040205322907175837548553044964889527773735859145148925452789317429441782859284412 332508832373214500733444001578313181477419744770452640715796767105059989494637309372776496559348095972296999315482", -// "1 662270332047780538236761160233282592027420752455270155418869852132492676666630700668832220500077525466061941018236 2299125391817702013055110693471044319922613065157535939085724616261923156462807520354440037023941486342197559986853", -// "1 539671814285151908354149493379775679230447318192963987668428133547804094161329213479620652127776798553660663411584 1503319234234984822166752674325584018890559572903102294038222208008964603696679883044023293697034293775749956692179", -// "1 1296246431649712555866080335511348675539520098184218301579333894833004472470244738946867536358943211935423055111558 1769793836751496188671353199640496137137574250307972332710165135300898774697581735572475470798279089231072331902299", -// "1 380145186617786820248621832307713531127003359562662906822571904797720854922616044101952325592420496820383385512579 1840140859664201837702586956346199014913668307776292190320451086631178028711553155893237996505496618826800059544115", -// "1 3114829031510841915621151916229561169189336605250941601689638461262358283048552069985585585970065241083080648099448 1331219795754692980309076688401603360766908614177898374418067681635672907558036412724043587283913495319664895110963", -// ]; - -// assert_eq!(expected.len(), proofs.len()); -// for (actual, expected) in proofs.iter().zip(expected) { -// assert_eq!(expected, actual.get_str(10)); -// } -// } - -// #[test] -// fn fr_fft_works_on_extended_data() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let chunk_len: usize = 16; -// let chunk_count: usize = 32; -// let n = chunk_len * chunk_count; -// let secret = Fr::from_str("1927409816240961209460912649124", 10).unwrap(); -// let kzg_curve = Curve::new(&secret, n * 2); -// let matrix = FK20Matrix::new(kzg_curve, n * 2, chunk_len, 10); -// let polynomial = build_protolambda_poly(chunk_count, chunk_len, n); - -// // Act -// let extended_poly = polynomial.get_extended(n * 2); -// let mut extended_data = matrix.kzg_settings.fft_settings.fft(&extended_poly.coeffs, false); -// order_by_rev_bit_order(&mut extended_data); - -// // Assert -// assert_eq!(1024, extended_data.len()); -// assert_eq!("23460229677428266615002007477956548356146403649357635172538975946710492134789", extended_data.last().unwrap().get_str(10)); -// } - -// #[test] -// fn fk20_multi_proof_full_circle_fixed_value() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let chunk_len: usize = 16; -// let chunk_count: usize = 32; -// let n = chunk_len * chunk_count; -// let n2 = n << 1; -// let secret = Fr::from_str("1927409816240961209460912649124", 10).unwrap(); -// let kzg_curve = Curve::new(&secret, n2); -// let matrix = FK20Matrix::new(kzg_curve, n2, chunk_len, 10); -// let polynomial = build_protolambda_poly(chunk_count, chunk_len, n); -// let proofs = matrix.dau_using_fk20_multi(&polynomial); -// let extended_poly = polynomial.get_extended(n2); -// let commitment = polynomial.commit(&matrix.kzg_settings.curve.g1_points); -// let mut extended_data = matrix.kzg_settings.fft_settings.fft(&extended_poly.coeffs, false); -// order_by_rev_bit_order(&mut extended_data); - -// // Act -// let domain_stride = matrix.kzg_settings.fft_settings.max_width / n2; -// for (pos, item) in proofs.iter().enumerate().take(chunk_count * 2) { -// let domain_pos = reverse_bits_limited(chunk_count, pos); -// let x = &matrix.kzg_settings.fft_settings.exp_roots_of_unity[domain_pos * domain_stride]; - -// let mut ys: Vec = extended_data.iter().copied() -// .skip(chunk_len * pos).take(chunk_len) -// .collect(); -// order_by_rev_bit_order(&mut ys); - -// let mut ys2 = vec![Fr::default(); chunk_len]; -// let stride = matrix.kzg_settings.fft_settings.max_width / chunk_len; -// let mut coset = vec![Fr::default(); chunk_len]; -// for i in 0..chunk_len { -// coset[i] = x * &matrix.kzg_settings.fft_settings.exp_roots_of_unity[i * stride]; -// ys2[i] = polynomial.eval_at(&coset[i]); -// } -// // Assert -// for (a, b) in ys.iter().zip(ys2) { -// assert_eq!(a.get_str(10), b.get_str(10)); -// } -// let proof = item; -// let valid = matrix.check_proof_multi(&commitment, proof, x, &ys); -// assert!(valid); -// } -// } - -// #[test] -// fn fk20_multi_proof_full_circle_random_secret() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let chunk_len: usize = 16; -// let chunk_count: usize = 32; -// let n = chunk_len * chunk_count; -// let n2 = n << 1; -// let mut secret = Fr::default(); -// secret.set_by_csprng(); -// let kzg_curve = Curve::new(&secret, n2); -// let matrix = FK20Matrix::new(kzg_curve, n2, chunk_len, 10); -// let polynomial = build_protolambda_poly(chunk_count, chunk_len, n); -// let proofs = matrix.dau_using_fk20_multi(&polynomial); -// let extended_poly = polynomial.get_extended(n2); -// let commitment = polynomial.commit(&matrix.kzg_settings.curve.g1_points); -// let mut extended_data = matrix.kzg_settings.fft_settings.fft(&extended_poly.coeffs, false); -// order_by_rev_bit_order(&mut extended_data); - -// // Act -// let domain_stride = matrix.kzg_settings.fft_settings.max_width / n2; -// for (pos, item) in proofs.iter().enumerate().take(chunk_count * 2) { -// let domain_pos = reverse_bits_limited(chunk_count, pos); -// let x = &matrix.kzg_settings.fft_settings.exp_roots_of_unity[domain_pos * domain_stride]; - -// let mut ys: Vec = extended_data.iter().copied() -// .skip(chunk_len * pos).take(chunk_len) -// .collect(); -// order_by_rev_bit_order(&mut ys); - -// let mut ys2 = vec![Fr::default(); chunk_len]; -// let stride = matrix.kzg_settings.fft_settings.max_width / chunk_len; -// let mut coset = vec![Fr::default(); chunk_len]; -// for i in 0..chunk_len { -// coset[i] = x * &matrix.kzg_settings.fft_settings.exp_roots_of_unity[i * stride]; -// ys2[i] = polynomial.eval_at(&coset[i]); -// } -// // Assert -// for (a, b) in ys.iter().zip(ys2) { -// assert_eq!(a.get_str(10), b.get_str(10)); -// } -// let proof = item; -// let valid = matrix.check_proof_multi(&commitment, proof, x, &ys); -// assert!(valid); -// } -// } - -// // DAS -// #[test] -// fn das_ftt_extension_should_extend_with_exact_values_given_known_inputs() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); - -// let settings = FFTSettings::new(4); -// let half = settings.max_width >> 1; -// let mut nums: Vec = (0..half).map(|x| Fr::from_int(x as i32)).collect(); - -// // Act -// settings.das_fft_extension(&mut nums); - -// // Assert -// let expected = [ -// "40848550508281085032507004530576241411780082424652766156356301038276798860159", -// "6142039928270026418094108197259568351390689035055085818561263188953927618475", -// "11587324666845105443475591151536072107134200545187128887977105192896420361353", -// "22364018979440222199939016627179319600179064631238957550218800890988804372329", -// "11587324666845105443475591151536072107134200545187128887977105192896420361353", -// "6142039928270026418094108197259568351390689035055085818561263188953927618475", -// "40848550508281085032507004530576241411780082424652766156356301038276798860159", -// "17787776339145915450250797138634814172282648860553994191802836368572645501264", -// ]; - -// assert_eq!(expected.len(), nums.len()); -// let all_values_equal = expected.iter().zip(expected.iter()).all(|(a, b)| a == b); -// assert!(all_values_equal); -// } - -// #[test] -// fn polynomial_recover_from_samples_should_recover_all_values_given_less_than_half_of_data_is_missing() { -// // Arrange -// assert!(init(CurveType::BLS12_381)); -// let settings = FFTSettings::new(10); - -// let coeffs: Vec = (0..((settings.max_width >> 1) as i32)).collect(); -// let poly = Polynomial::from_i32(&coeffs); -// // extend for redundancy -// let extended = poly.get_extended(settings.max_width); -// let data = settings.fft(&extended.coeffs, false); - -// // remove 1/4th of data -// let data_with_missing: Vec> = data -// .iter() -// .enumerate() -// .map(|(ix, entry)| { -// if ix % 4 == 0 { -// return None::; -// } -// Some(*entry) -// }).collect(); - -// // Act -// let recovered = Polynomial::recover_from_samples(&settings, &data_with_missing); - -// // Assert -// assert_eq!(data.len(), recovered.order()); -// for (i, item) in data.iter().enumerate() { -// assert_eq!(item.get_str(10), recovered.coeffs[i].get_str(10)); -// } -// } - -// // Helpers -// // Based on poly seen in TestKZGSettings_DAUsingFK20Multi -// // A poly that helps test edge cases of some Fr values, helps with informal correctness verification -// fn build_protolambda_poly(chunk_count: usize, chunk_len: usize, n: usize) -> Polynomial { -// assert!(init(CurveType::BLS12_381)); -// let mut poly_vals = vec![Fr::default(); n]; -// let v134 = Fr::from_int(134); -// for i in 0..chunk_count { -// let base: Vec = vec![1, 2, 3, 4 + i as i32, 7, 8 + (i*i) as i32, 9, 10, 13, 14, 1, 15, 0, 1000, 0, 33]; -// for j in 0..base.len() { -// poly_vals[i * chunk_len + j] = Fr::from_int(base[j]); -// } -// poly_vals[i * chunk_len + 12] = Fr::zero() - Fr::one(); -// poly_vals[i * chunk_len + 14] = Fr::zero() - v134; -// } - -// Polynomial::from_fr(poly_vals) -// } diff --git a/mcl/kzg-bench/src/test_macro.rs b/mcl/kzg-bench/src/test_macro.rs deleted file mode 100644 index e8c84d852..000000000 --- a/mcl/kzg-bench/src/test_macro.rs +++ /dev/null @@ -1,125 +0,0 @@ -macro_rules! field_test { - ($t:ty) => {{ - let mut x = <$t>::zero(); - assert!(x.is_valid()); - assert!(x.is_zero()); - assert!(!x.is_one()); - x.set_int(1); - assert!(!x.is_zero()); - assert!(x.is_one()); - let mut y = <$t>::from_int(1); - assert!(y.is_valid()); - assert_eq!(x, y); - y.set_int(2); - assert!(x != y); - x.set_str("65535", 10); - y.set_str("ffff", 16); - assert!(x.is_valid()); - assert_eq!(x, y); - x.set_int(123); - assert!(x.is_odd()); - x.set_int(124); - assert!(!x.is_odd()); - assert!(!x.is_negative()); - x.set_int(-124); - assert!(x.is_negative()); - - let mut z = <$t>::zero(); - let mut w = <$t>::zero(); - - let a = 256; - let b = 8; - x.set_int(a); - y.set_int(b); - <$t>::add(&mut z, &x, &y); - w.set_int(a + b); - assert_eq!(z, w); - assert_eq!(w, (&x + &y)); - z = x.clone(); - z += &y; - assert_eq!(z, w); - - <$t>::sub(&mut z, &x, &y); - w.set_int(a - b); - assert_eq!(z, w); - assert_eq!(w, (&x - &y)); - z = x.clone(); - z -= &y; - assert_eq!(z, w); - - <$t>::mul(&mut z, &x, &y); - w.set_int(a * b); - assert_eq!(z, w); - assert_eq!(w, (&x * &y)); - z = x.clone(); - z *= &y; - assert_eq!(z, w); - - <$t>::div(&mut z, &x, &y); - w.set_int(a / b); - assert_eq!(z, w); - assert_eq!(z, (&x / &y)); - z = x.clone(); - z /= &y; - assert_eq!(z, w); - - assert!(x.set_little_endian_mod(&[1, 2, 3, 4, 5])); - assert_eq!(x.get_str(16), "504030201"); - <$t>::sqr(&mut y, &x); - <$t>::mul(&mut z, &x, &x); - assert_eq!(y, z); - - assert!(<$t>::square_root(&mut w, &y)); - if w != x { - <$t>::neg(&mut z, &w); - assert_eq!(x, z); - } - }}; -} - -macro_rules! ec_test { - ($t:ty, $f:ty, $p:expr) => { - assert!($p.is_valid()); - assert!(!$p.is_zero()); - let mut p1 = <$t>::zero(); - assert!(p1.is_zero()); - assert_ne!(p1, $p); - <$t>::neg(&mut p1, &$p); - let mut x: $f = <$f>::zero(); - <$f>::neg(&mut x, &p1.y); - assert_eq!(&x, &$p.y); - - <$t>::dbl(&mut p1, &$p); - let mut p2: $t = <$t>::zero(); - let mut p3: $t = <$t>::zero(); - <$t>::add(&mut p2, &$p, &$p); - assert_eq!(p2, p1); - <$t>::add(&mut p3, &p2, &$p); - assert_eq!(p3, (&p2 + &$p)); - assert_eq!(p2, (&p3 - &$p)); - let mut y: Fr = Fr::from_int(1); - <$t>::mul(&mut p2, &$p, &y); - assert_eq!(p2, $p); - y.set_int(2); - <$t>::mul(&mut p2, &$p, &y); - assert_eq!(p2, p1); - y.set_int(3); - <$t>::mul(&mut p2, &$p, &y); - assert_eq!(p2, p3); - p2 = p1.clone(); - p2 += &$p; - assert_eq!(p2, p3); - - p2 -= &$p; - assert_eq!(p2, p1); - }; -} - -macro_rules! serialize_test { - ($t:ty, $x:expr) => { - let buf = $x.serialize(); - let mut y: $t = <$t>::zero(); - assert!(y.deserialize(&buf)); - assert_eq!($x, y); - }; -} diff --git a/mcl/kzg/Cargo.toml b/mcl/kzg/Cargo.toml deleted file mode 100644 index 718f88e65..000000000 --- a/mcl/kzg/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "rust-kzg-mcl" -version = "0.0.1" -authors = ["MITSUNARI Shigeo "] -description = "a wrapper class/function of a pairing library; https://github.com/herumi/mcl" -license = "BSD-3-Clause OR MIT OR Apache-2.0" -edition = "2021" - -[dependencies] -cc = "1.0" -blst = "0.3.11" -kzg = { path = "../../kzg" } -primitive-types = "0.12.0" -rayon = { version = "1.5.1", optional = true } -once_cell = "1.4.0" -libc = "0.2.139" -num_cpus = "1.15.0" -hex = "0.4.2" - -[features] -parallel = ["rayon", "kzg/parallel"] - -[build-dependencies] -cc = "1.0" diff --git a/mcl/kzg/build.rs b/mcl/kzg/build.rs deleted file mode 100644 index 7038eb66a..000000000 --- a/mcl/kzg/build.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::env; -use std::process::Command; - -fn main() { - let cargo_manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - let out_dir = env::var("OUT_DIR").unwrap(); - - if !Command::new("sh") - .arg(format!("{}/build.sh", cargo_manifest_dir)) - .current_dir(out_dir.clone()) - .status() - .expect("Failed to build") - .success() - { - panic!("Built script failed"); - } - - println!("cargo:rustc-link-search={}/lib", out_dir); -} diff --git a/mcl/kzg/build.sh b/mcl/kzg/build.sh deleted file mode 100755 index efe730da4..000000000 --- a/mcl/kzg/build.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -echo "Removing old mcl lib" -rm -rf lib/* mcl -mkdir -p lib - -echo "Cloning mcl" -git clone https://github.com/herumi/mcl.git -cd mcl || exit 1 - -echo "Building mcl" -make -j$(nproc) -f Makefile MCL_USE_GMP=0 - -echo "Preparing mcl crate" -cd .. -cp mcl/lib/libmcl.a lib/ -cp mcl/lib/libmclbn384_256.a lib/ - -echo "Cleaning up" -rm -rf mcl/ diff --git a/mcl/kzg/csharp.patch b/mcl/kzg/csharp.patch deleted file mode 100644 index 1de0ee1ae..000000000 --- a/mcl/kzg/csharp.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 4989dace3b71ebb422ca86545f937f8d3c77031a Mon Sep 17 00:00:00 2001 -From: belijzajac -Date: Tue, 7 Mar 2023 20:50:46 +0200 -Subject: [PATCH] Update linking - ---- - bindings/csharp/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/bindings/csharp/Makefile b/bindings/csharp/Makefile -index d5fa3dc..0a77983 100644 ---- a/bindings/csharp/Makefile -+++ b/bindings/csharp/Makefile -@@ -31,7 +31,7 @@ endif - - FIELD_ELEMENTS_PER_BLOB ?= 4096 - INCLUDE_DIRS = ../../src ../../blst/bindings --TARGETS = ckzg.c ../../src/c_kzg_4844.c ../../blst/$(BLST_OBJ) -+TARGETS = ckzg.c ../../../../../target/release/rust_kzg_mcl.a - - CFLAGS += -O2 -Wall -Wextra -shared - CFLAGS += -DFIELD_ELEMENTS_PER_BLOB=$(FIELD_ELEMENTS_PER_BLOB) --- -2.39.2 - diff --git a/mcl/kzg/go.patch b/mcl/kzg/go.patch deleted file mode 100644 index 04bfdc486..000000000 --- a/mcl/kzg/go.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 01b1c2cc872f0fa57414f69fed5604934aeb6421 Mon Sep 17 00:00:00 2001 -From: belijzajac -Date: Tue, 11 Apr 2023 19:04:53 +0300 -Subject: [PATCH] Update linking - ---- - bindings/go/main.go | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/bindings/go/main.go b/bindings/go/main.go -index aa7f141..1357122 100644 ---- a/bindings/go/main.go -+++ b/bindings/go/main.go -@@ -5,7 +5,15 @@ package ckzg4844 - // #ifndef FIELD_ELEMENTS_PER_BLOB - // #define FIELD_ELEMENTS_PER_BLOB 4096 - // #endif --// #include "c_kzg_4844.c" -+// #ifndef BYTES_PER_G1 -+// #define BYTES_PER_G1 48 -+// #endif -+// #ifndef BYTES_PER_G2 -+// #define BYTES_PER_G2 96 -+// #endif -+// #include -+// #include "c_kzg_4844.h" -+// #cgo LDFLAGS: -L${SRCDIR}/../../../../../target/release -L${SRCDIR}/../../lib -l:rust_kzg_mcl.a -lstdc++ -lblst -lm - import "C" - - import ( --- -2.40.0 - diff --git a/mcl/kzg/java.patch b/mcl/kzg/java.patch deleted file mode 100644 index 9f8df7e08..000000000 --- a/mcl/kzg/java.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 8dceb719c2ca01583bd403a59d441949e7f2a695 Mon Sep 17 00:00:00 2001 -From: belijzajac -Date: Thu, 23 Feb 2023 13:25:15 +0200 -Subject: [PATCH] Update linking - ---- - bindings/java/Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/bindings/java/Makefile b/bindings/java/Makefile -index 4eb21ce..184e501 100644 ---- a/bindings/java/Makefile -+++ b/bindings/java/Makefile -@@ -1,6 +1,6 @@ - INCLUDE_DIRS = ../../src ../../blst/bindings - --TARGETS=c_kzg_4844_jni.c ../../src/c_kzg_4844.c ../../lib/libblst.a -+TARGETS=c_kzg_4844_jni.c ../../../../../target/release/rust_kzg_mcl.a - - CC_FLAGS= - OPTIMIZATION_LEVEL=-O2 --- -2.39.2 - diff --git a/mcl/kzg/nodejs.patch b/mcl/kzg/nodejs.patch deleted file mode 100644 index 229ee0ee8..000000000 --- a/mcl/kzg/nodejs.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 344b90e309d605d454cbb962da0531bcb062b11a Mon Sep 17 00:00:00 2001 -From: belijzajac -Date: Sat, 17 Jun 2023 19:16:04 +0300 -Subject: [PATCH] Update linking - ---- - bindings/node.js/Makefile | 1 - - bindings/node.js/binding.gyp | 37 +++++------------------------------- - bindings/node.js/src/kzg.cxx | 4 ++++ - 3 files changed, 9 insertions(+), 33 deletions(-) - -diff --git a/bindings/node.js/Makefile b/bindings/node.js/Makefile -index fdf1618..34e54df 100644 ---- a/bindings/node.js/Makefile -+++ b/bindings/node.js/Makefile -@@ -31,7 +31,6 @@ build: install clean - @# Prepare the dependencies directory - @mkdir -p deps/c-kzg - @cp -r ../../blst deps -- @cp ../../src/c_kzg_4844.c deps/c-kzg - @cp ../../src/c_kzg_4844.h deps/c-kzg - @# Build the bindings - @$(YARN) node-gyp --loglevel=warn configure -diff --git a/bindings/node.js/binding.gyp b/bindings/node.js/binding.gyp -index 69be3ef..349ac0b 100644 ---- a/bindings/node.js/binding.gyp -+++ b/bindings/node.js/binding.gyp -@@ -3,44 +3,17 @@ - { - "target_name": "kzg", - "sources": [ -- "src/kzg.cxx", -- "deps/blst/src/server.c", -- "deps/c-kzg/c_kzg_4844.c" -+ "src/kzg.cxx" - ], - "include_dirs": [ - "<(module_root_dir)/deps/blst/bindings", - "<(module_root_dir)/deps/c-kzg", - " --- -2.40.1 - diff --git a/mcl/kzg/python.patch b/mcl/kzg/python.patch deleted file mode 100644 index b75204d44..000000000 --- a/mcl/kzg/python.patch +++ /dev/null @@ -1,49 +0,0 @@ -From ac8a609604adea4ffa36e3961a0a30b1c46188b9 Mon Sep 17 00:00:00 2001 -From: belijzajac -Date: Thu, 23 Mar 2023 21:36:48 +0200 -Subject: [PATCH] Update linking - ---- - bindings/python/Makefile | 5 +---- - bindings/python/setup.py | 6 +++--- - 2 files changed, 4 insertions(+), 7 deletions(-) - -diff --git a/bindings/python/Makefile b/bindings/python/Makefile -index 7361590..635d1dd 100644 ---- a/bindings/python/Makefile -+++ b/bindings/python/Makefile -@@ -1,11 +1,8 @@ - .PHONY: all - all: install test ecc_test - --../../src/c_kzg_4844.o: -- make -C../../src c_kzg_4844.o -- - .PHONY: install --install: setup.py ckzg.c ../../src/c_kzg_4844.o -+install: setup.py ckzg.c - python3 setup.py install - - .PHONY: test -diff --git a/bindings/python/setup.py b/bindings/python/setup.py -index bf969cb..9179129 100644 ---- a/bindings/python/setup.py -+++ b/bindings/python/setup.py -@@ -8,11 +8,11 @@ def main(): - ext_modules=[ - Extension( - "ckzg", -- sources=["ckzg.c", "../../src/c_kzg_4844.c"], -+ sources=["ckzg.c"], - include_dirs=["../../inc", "../../src"], - define_macros=[("FIELD_ELEMENTS_PER_BLOB", "4096")], -- library_dirs=["../../lib"], -- libraries=["blst"])]) -+ library_dirs=["../../lib", "../../../../../target/release"], -+ libraries=[":rust_kzg_mcl.a", "stdc++"])]) - - if __name__ == "__main__": - main() --- -2.40.0 - diff --git a/mcl/kzg/rust.patch b/mcl/kzg/rust.patch deleted file mode 100644 index 8a56b433a..000000000 --- a/mcl/kzg/rust.patch +++ /dev/null @@ -1,82 +0,0 @@ -From bde067761f5b3f991cdb88ea6b2b0fd36c774721 Mon Sep 17 00:00:00 2001 -From: belijzajac -Date: Tue, 11 Apr 2023 16:50:07 +0300 -Subject: [PATCH] Update linking - ---- - bindings/rust/Cargo.toml | 1 + - bindings/rust/build.rs | 23 +++++------------------ - 2 files changed, 6 insertions(+), 18 deletions(-) - -diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml -index b827723..a415303 100644 ---- a/bindings/rust/Cargo.toml -+++ b/bindings/rust/Cargo.toml -@@ -1,3 +1,4 @@ -+[workspace] - [package] - name = "c-kzg" - version = "0.1.0" -diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs -index d2dba36..ac4153f 100644 ---- a/bindings/rust/build.rs -+++ b/bindings/rust/build.rs -@@ -8,6 +8,7 @@ const MINIMAL_FIELD_ELEMENTS_PER_BLOB: usize = 4; - // - // NOTE: This code is taken from https://github.com/supranational/blst `build.rs` `main`. The crate - // is not used as a depedency to avoid double link issues on dependants. -+#[allow(dead_code)] - fn compile_blst(blst_base_dir: PathBuf) { - // account for cross-compilation [by examining environment variables] - let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); -@@ -98,6 +99,7 @@ fn compile_blst(blst_base_dir: PathBuf) { - } - - /// Adds assembly files for blst compilation. -+#[allow(dead_code)] - fn blst_assembly(file_vec: &mut Vec, base_dir: &Path, _arch: &String) { - #[cfg(target_env = "msvc")] - if env::var("CARGO_CFG_TARGET_ENV").unwrap().eq("msvc") { -@@ -134,28 +136,12 @@ fn main() { - eprintln!("Using FIELD_ELEMENTS_PER_BLOB={}", field_elements_per_blob); - - let blst_base_dir = root_dir.join("blst"); -- compile_blst(blst_base_dir.clone()); -+ let rust_kzg_target_dir = root_dir.join("../../../target/release/"); - - // Obtain the header files of blst - let blst_headers_dir = blst_base_dir.join("bindings"); -- - let c_src_dir = root_dir.join("src"); - -- let mut cc = cc::Build::new(); -- -- #[cfg(windows)] -- cc.flag("-D_CRT_SECURE_NO_WARNINGS"); -- -- cc.include(blst_headers_dir.clone()); -- cc.warnings(false); -- cc.flag(format!("-DFIELD_ELEMENTS_PER_BLOB={}", field_elements_per_blob).as_str()); -- cc.file(c_src_dir.join("c_kzg_4844.c")); -- -- cc.try_compile("ckzg").expect("Failed to compile ckzg"); -- -- // Tell cargo to search for the static blst exposed by the blst-bindings' crate. -- println!("cargo:rustc-link-lib=static=blst"); -- - let bindings_out_path = cargo_dir.join("src").join("bindings").join("generated.rs"); - let header_file_path = c_src_dir.join("c_kzg_4844.h"); - let header_file = header_file_path.to_str().expect("valid header file"); -@@ -168,7 +154,8 @@ fn main() { - ); - - // Finally, tell cargo this provides ckzg -- println!("cargo:rustc-link-lib=ckzg"); -+ println!("cargo:rustc-link-search={}", rust_kzg_target_dir.display()); -+ println!("cargo:rustc-link-arg=-l:rust_kzg_mcl.a"); - } - - fn make_bindings

( --- -2.40.0 - diff --git a/mcl/kzg/src/c_bindings.rs b/mcl/kzg/src/c_bindings.rs deleted file mode 100644 index fac419af6..000000000 --- a/mcl/kzg/src/c_bindings.rs +++ /dev/null @@ -1,366 +0,0 @@ -use crate::data_types::{fp::*, fr::*, g2::*}; -use crate::fk20_fft::FFTSettings as mFFTSettings; -use crate::kzg_settings::KZGSettings as mKZGSettings; -use kzg::cfg_into_iter; -use kzg::eip_4844::{ - blst_p1, load_trusted_setup_string, Blob, Bytes32, Bytes48, CFFTSettings, CKZGSettings, - KZGCommitment, KZGProof, BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, C_KZG_RET, - C_KZG_RET_BADARGS, C_KZG_RET_OK, -}; -use std::boxed::Box; -use std::slice::{from_raw_parts, from_raw_parts_mut}; - -use crate::data_types::g1::G1; -use kzg::G1 as CommonG1; - -#[cfg(feature = "parallel")] -use rayon::prelude::*; - -unsafe fn cg1_to_g1(t: *const blst_p1) -> G1 { - G1 { - x: Fp { d: (*t).x.l }, - y: Fp { d: (*t).y.l }, - z: Fp { d: (*t).z.l }, - } -} - -unsafe fn ks_to_cks(t: &mut mKZGSettings, out: *mut CKZGSettings) { - assert_eq!(t.curve.g1_points.len(), t.fft_settings.max_width); - (*out).g1_values = t.curve.g1_points.as_mut_ptr() as _; - (*out).g2_values = t.curve.g2_points.as_mut_ptr() as _; - let fs = CFFTSettings { - max_width: t.fft_settings.max_width as _, - roots_of_unity: t.fft_settings.expanded_roots_of_unity.as_mut_ptr() as _, - expanded_roots_of_unity: t.fft_settings.expanded_roots_of_unity.as_mut_ptr() as _, - reverse_roots_of_unity: t.fft_settings.reverse_roots_of_unity.as_mut_ptr() as _, - }; - let b = Box::new(fs); - (*out).fs = Box::into_raw(b); -} - -unsafe fn cks_to_ks(t: *const CKZGSettings) -> mKZGSettings { - crate::fk20_fft::init_globals(); - let fs = (*t).fs; - let mw = (*fs).max_width as usize; - let mut ks = mKZGSettings { - curve: crate::kzg10::Curve { - g1_gen: G1::gen(), - g2_gen: G2::gen(), - g1_points: Vec::from_raw_parts((*t).g1_values as _, mw, mw), - g2_points: Vec::from_raw_parts((*t).g2_values as _, 65, 65), - }, - fft_settings: mFFTSettings { - max_width: mw, - root_of_unity: Fr::default(), - expanded_roots_of_unity: Vec::from_raw_parts( - (*fs).expanded_roots_of_unity as _, - mw + 1, - mw + 1, - ), - reverse_roots_of_unity: Vec::from_raw_parts( - (*fs).reverse_roots_of_unity as _, - mw + 1, - mw + 1, - ), - roots_of_unity: Vec::from_raw_parts((*fs).roots_of_unity as _, mw + 1, mw + 1), - }, - }; - ks.fft_settings.root_of_unity = ks.fft_settings.expanded_roots_of_unity[1]; - ks -} - -unsafe fn deserialize_blob(blob: *const Blob) -> Result, C_KZG_RET> { - (*blob) - .bytes - .chunks(BYTES_PER_FIELD_ELEMENT) - .map(|chunk| { - let mut bytes = [0u8; BYTES_PER_FIELD_ELEMENT]; - bytes.copy_from_slice(chunk); - let mut tmp = Fr::default(); - let ret = tmp.deserialize(&bytes); - if !ret { - Err(C_KZG_RET_BADARGS) - } else { - Ok(tmp) - } - // fix for `test_verify_kzg_proof_batch__fails_with_incorrect_proof` c-kzg-4844 test - //if let Ok(fr) = crate::eip_4844::bytes_to_bls_field(&bytes) { - // Ok(fr) - //} else { - // Err(C_KZG_RET_BADARGS) - //} - }) - .collect::, C_KZG_RET>>() -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn bytes_from_g1(out: *mut u8, in_: *const blst_p1) { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - let b = cg1_to_g1(in_).to_bytes(); - let res = from_raw_parts_mut(out, b.len()); - res.copy_from_slice(&b); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn load_trusted_setup( - out: *mut CKZGSettings, - g1_bytes: *const u8, - n1: usize, - g2_bytes: *const u8, - n2: usize, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - let mut mks = crate::eip_4844::load_trusted_setup_from_bytes( - from_raw_parts(g1_bytes, n1 * BYTES_PER_G1), - from_raw_parts(g2_bytes, n2 * BYTES_PER_G2), - ); - ks_to_cks(&mut mks, out); - std::mem::forget(mks); - C_KZG_RET_OK -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn load_trusted_setup_file( - out: *mut CKZGSettings, - in_: *mut libc::FILE, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - - let mut buf = vec![0u8; 1024 * 1024]; - let len: usize = libc::fread(buf.as_mut_ptr() as *mut libc::c_void, 1, buf.len(), in_); - let s = String::from_utf8(buf[..len].to_vec()).unwrap(); - - let (g1_bytes, g2_bytes) = load_trusted_setup_string(&s); - let mut mks = - crate::eip_4844::load_trusted_setup_from_bytes(g1_bytes.as_slice(), g2_bytes.as_slice()); - ks_to_cks(&mut mks, out); - std::mem::forget(mks); - - C_KZG_RET_OK -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn free_trusted_setup(s: *mut CKZGSettings) { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - drop(cks_to_ks(s)); - let fs = Box::from_raw((*s).fs as *mut CFFTSettings); - drop(fs); -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn compute_blob_kzg_proof( - out: *mut KZGProof, - blob: *const Blob, - commitment_bytes: *const Bytes48, - s: &CKZGSettings, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - - let deserialized_blob = deserialize_blob(blob); - if deserialized_blob.is_err() { - return deserialized_blob.err().unwrap(); - } - let commitment_g1 = G1::from_bytes(&(*commitment_bytes).bytes); - if commitment_g1.is_err() { - return C_KZG_RET_BADARGS; - } - - let ms = cks_to_ks(s); - let proof = crate::eip_4844::compute_blob_kzg_proof( - &deserialized_blob.unwrap(), - &commitment_g1.unwrap(), - &ms, - ); - std::mem::forget(ms); - - if let Ok(proof) = proof { - (*out).bytes = proof.to_bytes(); - C_KZG_RET_OK - } else { - C_KZG_RET_BADARGS - } -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn verify_blob_kzg_proof( - ok: *mut bool, - blob: *const Blob, - commitment_bytes: *const Bytes48, - proof_bytes: *const Bytes48, - s: &CKZGSettings, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - - let deserialized_blob = deserialize_blob(blob); - if deserialized_blob.is_err() { - return deserialized_blob.err().unwrap(); - } - let commitment_g1 = G1::from_bytes(&(*commitment_bytes).bytes); - let proof_g1 = G1::from_bytes(&(*proof_bytes).bytes); - if commitment_g1.is_err() || proof_g1.is_err() { - return C_KZG_RET_BADARGS; - } - - let ms = cks_to_ks(s); - let result = crate::eip_4844::verify_blob_kzg_proof( - &deserialized_blob.unwrap(), - &commitment_g1.unwrap(), - &proof_g1.unwrap(), - &ms, - ); - std::mem::forget(ms); - - if let Ok(result) = result { - *ok = result; - C_KZG_RET_OK - } else { - C_KZG_RET_BADARGS - } -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn verify_blob_kzg_proof_batch( - ok: *mut bool, - blobs: *const Blob, - commitments_bytes: *const Bytes48, - proofs_bytes: *const Bytes48, - n: usize, - s: &CKZGSettings, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - - let raw_blobs = from_raw_parts(blobs, n); - let raw_commitments = from_raw_parts(commitments_bytes, n); - let raw_proofs = from_raw_parts(proofs_bytes, n); - - let deserialized_blobs: Result>, C_KZG_RET> = cfg_into_iter!(raw_blobs) - .map(|raw_blob| deserialize_blob(raw_blob).map_err(|_| C_KZG_RET_BADARGS)) - .collect(); - - let commitments_g1: Result, C_KZG_RET> = cfg_into_iter!(raw_commitments) - .map(|raw_commitment| G1::from_bytes(&raw_commitment.bytes).map_err(|_| C_KZG_RET_BADARGS)) - .collect(); - - let proofs_g1: Result, C_KZG_RET> = cfg_into_iter!(raw_proofs) - .map(|raw_proof| G1::from_bytes(&raw_proof.bytes).map_err(|_| C_KZG_RET_BADARGS)) - .collect(); - - if let (Ok(blobs), Ok(commitments), Ok(proofs)) = - (deserialized_blobs, commitments_g1, proofs_g1) - { - let ms = cks_to_ks(s); - let result = crate::eip_4844::verify_blob_kzg_proof_batch( - blobs.as_slice(), - &commitments, - &proofs, - &ms, - ); - std::mem::forget(ms); - - if let Ok(result) = result { - *ok = result; - C_KZG_RET_OK - } else { - C_KZG_RET_BADARGS - } - } else { - *ok = false; - C_KZG_RET_BADARGS - } -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn blob_to_kzg_commitment( - out: *mut KZGCommitment, - blob: *const Blob, - s: *const CKZGSettings, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - - let deserialized_blob = deserialize_blob(blob); - if deserialized_blob.is_err() { - return deserialized_blob.err().unwrap(); - } - let ms = cks_to_ks(s); - let tmp = crate::eip_4844::blob_to_kzg_commitment(&deserialized_blob.unwrap(), &ms); - (*out).bytes = G1::to_bytes(&tmp); - std::mem::forget(ms); - - C_KZG_RET_OK -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn verify_kzg_proof( - ok: *mut bool, - commitment_bytes: *const Bytes48, - z_bytes: *const Bytes32, - y_bytes: *const Bytes32, - proof_bytes: *const Bytes48, - s: *const CKZGSettings, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - - let frz = Fr::from_bytes(&(*z_bytes).bytes); - let fry = Fr::from_bytes(&(*y_bytes).bytes); - let g1commitment = G1::from_bytes(&(*commitment_bytes).bytes); - let g1proof = G1::from_bytes(&(*proof_bytes).bytes); - - if frz.is_err() || fry.is_err() || g1commitment.is_err() || g1proof.is_err() { - return C_KZG_RET_BADARGS; - } - - let ms = cks_to_ks(s); - let result = crate::eip_4844::verify_kzg_proof( - &g1commitment.unwrap(), - &frz.unwrap(), - &fry.unwrap(), - &g1proof.unwrap(), - &ms, - ); - std::mem::forget(ms); - - if let Ok(result) = result { - *ok = result; - C_KZG_RET_OK - } else { - C_KZG_RET_BADARGS - } -} - -/// # Safety -#[no_mangle] -pub unsafe extern "C" fn compute_kzg_proof( - proof_out: *mut KZGProof, - y_out: *mut Bytes32, - blob: *const Blob, - z_bytes: *const Bytes32, - s: *const CKZGSettings, -) -> C_KZG_RET { - assert!(crate::mcl_methods::init(crate::CurveType::BLS12_381)); - - let deserialized_blob = deserialize_blob(blob); - if deserialized_blob.is_err() { - return deserialized_blob.err().unwrap(); - } - let frz = Fr::from_bytes(&(*z_bytes).bytes); - if frz.is_err() { - return C_KZG_RET_BADARGS; - } - let ms = cks_to_ks(s); - let (proof_out_tmp, fry_tmp) = - crate::eip_4844::compute_kzg_proof(&deserialized_blob.unwrap(), &frz.unwrap(), &ms); - (*proof_out).bytes = G1::to_bytes(&proof_out_tmp); - (*y_out).bytes = Fr::to_bytes(&fry_tmp); - std::mem::forget(ms); - - C_KZG_RET_OK -} diff --git a/mcl/kzg/src/das.rs b/mcl/kzg/src/das.rs deleted file mode 100644 index 6b1515c87..000000000 --- a/mcl/kzg/src/das.rs +++ /dev/null @@ -1,87 +0,0 @@ -use kzg::common_utils::is_power_of_2; - -use crate::data_types::fr::Fr; -use crate::fk20_fft::*; - -impl FFTSettings { - pub fn das_fft_extension(&self, values: &mut [Fr]) -> Result<(), String> { - if values.is_empty() { - return Err(String::from("Values cannot be empty")); - } - if !is_power_of_2(values.len()) { - return Err(String::from("Value count must be a number of two")); - } - if values.len() << 1 > self.max_width { - return Err(String::from("ftt settings max width too small!")); - } - - //larger stride if more roots fttsettings - let stride = self.max_width / (values.len() * 2); - self._das_fft_extension(values, stride); - // just dividing every value by 1/(2**depth) aka length - // TODO: what's faster, maybe vec[x] * vec[x], ask herumi to implement? - let inv_length = Fr::from_int(values.len() as i32).get_inv(); - for item in values.iter_mut() { - *item *= &inv_length; - } - Ok(()) - } - - // #[cfg(feature = "parallel")] - fn _das_fft_extension(&self, values: &mut [Fr], stride: usize) { - if values.len() < 2 { - return; - } - if values.len() == 2 { - let (x, y) = FFTSettings::_calc_add_and_sub(&values[0], &values[1]); - - let temp = y * self.expanded_roots_of_unity[stride]; - values[0] = x + temp; - values[1] = x - temp; - return; - } - - let length = values.len(); - let half = length >> 1; - - for i in 0..half { - let (add, sub) = FFTSettings::_calc_add_and_sub(&values[i], &values[half + i]); - values[half + i] = sub * self.reverse_roots_of_unity[(i << 1) * stride]; - values[i] = add; - } - - #[cfg(feature = "parallel")] - { - if values.len() > 32 { - let (lo, hi) = values.split_at_mut(half); - rayon::join( - || self._das_fft_extension(hi, stride * 2), - || self._das_fft_extension(lo, stride * 2), - ); - } else { - self._das_fft_extension(&mut values[..half], stride << 1); - self._das_fft_extension(&mut values[half..], stride << 1); - } - } - #[cfg(not(feature = "parallel"))] - { - // left - self._das_fft_extension(&mut values[..half], stride << 1); - // right - self._das_fft_extension(&mut values[half..], stride << 1); - } - - for i in 0..half { - let root = &self.expanded_roots_of_unity[((i << 1) + 1) * stride]; - let y_times_root = &values[half + i] * root; - - let (add, sub) = FFTSettings::_calc_add_and_sub(&values[i], &y_times_root); - values[i] = add; - values[i + half] = sub; - } - } - - fn _calc_add_and_sub(a: &Fr, b: &Fr) -> (Fr, Fr) { - (a + b, a - b) - } -} diff --git a/mcl/kzg/src/data_recovery.rs b/mcl/kzg/src/data_recovery.rs deleted file mode 100644 index c50960b55..000000000 --- a/mcl/kzg/src/data_recovery.rs +++ /dev/null @@ -1,216 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::fk20_fft::*; -use crate::kzg10::*; -#[cfg(feature = "parallel")] -use crate::utilities::next_pow_of_2; -use kzg::common_utils::is_power_of_2; -#[cfg(feature = "parallel")] -use once_cell::sync::OnceCell; - -#[cfg(feature = "parallel")] -static INVERSE_FACTORS: OnceCell> = OnceCell::new(); -#[cfg(feature = "parallel")] -static UNSHIFT_FACTOR_POWERS: OnceCell> = OnceCell::new(); - -impl Polynomial { - #[allow(clippy::needless_range_loop)] - pub fn shift_in_place(&mut self) { - let inv_factor = Fr::from_int(PRIMITIVE_ROOT).get_inv(); - #[cfg(feature = "parallel")] - { - let factors = INVERSE_FACTORS.get_or_init(|| { - let mut temp: Vec = vec![Fr::one()]; - for i in 1..65536 { - let mut res = Fr::zero(); - Fr::mul(&mut res, &temp[i - 1], &inv_factor); - - temp.push(res); - } - - temp - }); - - for i in 1..self.order() { - self.coeffs[i] *= &factors[i]; - } - } - #[cfg(not(feature = "parallel"))] - { - self._shift_in_place(&inv_factor); - } - } - - #[allow(clippy::needless_range_loop)] - pub fn unshift_in_place(&mut self) { - let scale_factor = Fr::from_int(PRIMITIVE_ROOT); - #[cfg(feature = "parallel")] - { - let factors = UNSHIFT_FACTOR_POWERS.get_or_init(|| { - let mut temp: Vec = vec![Fr::one()]; - for i in 1..65536 { - let mut res = Fr::zero(); - Fr::mul(&mut res, &temp[i - 1], &scale_factor); - - temp.push(res); - } - - temp - }); - - for i in 1..self.order() { - self.coeffs[i] *= &factors[i]; - } - } - #[cfg(not(feature = "parallel"))] - { - self._shift_in_place(&scale_factor); - } - } - - //TODO, use precalculated tables for factors? - fn _shift_in_place(&mut self, factor: &Fr) { - let mut factor_to_power = Fr::one(); - for i in 0..self.order() { - self.coeffs[i] *= &factor_to_power; - factor_to_power *= factor; - } - } - - pub fn recover_coeffs_from_samples( - fft_settings: &FFTSettings, - samples: &[Option], - ) -> Result { - if !is_power_of_2(samples.len()) { - return Err(String::from("length of samples must be a power of two")); - } - - let missing_data_indices: Vec = samples - .iter() - .enumerate() - .filter(|(_, ex)| ex.is_none()) - .map(|(ix, _)| ix) - .collect(); - - if missing_data_indices.len() > samples.len() / 2 { - return Err(String::from( - "Impossible to recover, too many shards are missing", - )); - } - - let (zero_eval, zero_poly_coeffs) = - fft_settings.zero_poly_via_multiplication(samples.len(), &missing_data_indices)?; - - // TODO: possible optimization, remove clone() - let poly_evals_with_zero: Vec = samples - .iter() - .zip(zero_eval) - .map(|(x, eval)| { - if x.is_none() { - return Fr::zero(); - } - (*x).unwrap() * eval - }) - .collect(); - - let poly_with_zero_coeffs = fft_settings.fft(&poly_evals_with_zero, true).unwrap(); - let mut poly_with_zero = Polynomial::from_fr(poly_with_zero_coeffs); - let mut zero_poly = Polynomial::from_fr(zero_poly_coeffs.coeffs); - - #[cfg(feature = "parallel")] - let optim = next_pow_of_2(poly_with_zero.order() - 1); - - #[cfg(feature = "parallel")] - { - if optim > 1024 { - rayon::join( - || poly_with_zero.shift_in_place(), - || zero_poly.shift_in_place(), - ); - } else { - poly_with_zero.shift_in_place(); - zero_poly.shift_in_place(); - } - } - - #[cfg(not(feature = "parallel"))] - { - poly_with_zero.shift_in_place(); - zero_poly.shift_in_place(); - } - - let eval_shifted_poly_with_zero: Vec; - let eval_shifted_zero_poly: Vec; - - #[cfg(not(feature = "parallel"))] - { - eval_shifted_poly_with_zero = fft_settings.fft(&poly_with_zero.coeffs, false).unwrap(); - eval_shifted_zero_poly = fft_settings.fft(&zero_poly.coeffs, false).unwrap(); - } - - #[cfg(feature = "parallel")] - { - if optim > 1024 { - let mut eval_shifted_poly_with_zero_temp = vec![]; - let mut eval_shifted_zero_poly_temp = vec![]; - - rayon::join( - || { - eval_shifted_poly_with_zero_temp = - fft_settings.fft(&poly_with_zero.coeffs, false).unwrap() - }, - || { - eval_shifted_zero_poly_temp = - fft_settings.fft(&zero_poly.coeffs, false).unwrap() - }, - ); - - eval_shifted_poly_with_zero = eval_shifted_poly_with_zero_temp; - eval_shifted_zero_poly = eval_shifted_zero_poly_temp; - } else { - eval_shifted_poly_with_zero = - fft_settings.fft(&poly_with_zero.coeffs, false).unwrap(); - eval_shifted_zero_poly = fft_settings.fft(&zero_poly.coeffs, false).unwrap(); - } - } - - let eval_shifted_reconstructed_poly: Vec = eval_shifted_poly_with_zero - .iter() - .zip(eval_shifted_zero_poly) - .map(|(a, b)| a / &b) - .collect(); - - let shifted_reconstructed_poly_coeffs = fft_settings - .fft(&eval_shifted_reconstructed_poly, true) - .unwrap(); - let mut shifted_reconstructed_poly = Polynomial::from_fr(shifted_reconstructed_poly_coeffs); - shifted_reconstructed_poly.unshift_in_place(); - - Ok(shifted_reconstructed_poly) - } - - pub fn recover_from_samples( - fft_settings: &FFTSettings, - samples: &[Option], - ) -> Result { - let reconstructed_data = fft_settings - .fft( - &Self::recover_coeffs_from_samples(fft_settings, samples)?.coeffs, - false, - ) - .unwrap(); - - Ok(Polynomial::from_fr(reconstructed_data)) - } - - pub fn unwrap_default(values: &[Option]) -> Vec { - return values - .iter() - .map(|x| { - if x.is_none() { - return Fr::zero(); - } - (*x).unwrap() - }) - .collect(); - } -} diff --git a/mcl/kzg/src/data_types/fp.rs b/mcl/kzg/src/data_types/fp.rs deleted file mode 100644 index a7c268ab1..000000000 --- a/mcl/kzg/src/data_types/fp.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::mcl_methods::*; -use std::ops::{Add, AddAssign}; -use std::ops::{Div, DivAssign}; -use std::ops::{Mul, MulAssign}; -use std::ops::{Sub, SubAssign}; -use std::os::raw::c_int; - -#[link(name = "mcl", kind = "static")] -#[link(name = "mclbn384_256", kind = "static")] -#[link(name = "stdc++")] -#[allow(non_snake_case)] -extern "C" { - fn mclBnFp_isEqual(x: *const Fp, y: *const Fp) -> i32; - fn mclBnFp_isValid(x: *const Fp) -> i32; - fn mclBnFp_isZero(x: *const Fp) -> i32; - fn mclBnFp_isOne(x: *const Fp) -> i32; - fn mclBnFp_isOdd(x: *const Fp) -> i32; - fn mclBnFp_isNegative(x: *const Fp) -> i32; - - fn mclBnFp_setStr(x: *mut Fp, buf: *const u8, bufSize: usize, ioMode: i32) -> c_int; - fn mclBnFp_getStr(buf: *mut u8, maxBufSize: usize, x: *const Fp, ioMode: i32) -> usize; - fn mclBnFp_serialize(buf: *mut u8, maxBufSize: usize, x: *const Fp) -> usize; - fn mclBnFp_deserialize(x: *mut Fp, buf: *const u8, bufSize: usize) -> usize; - - fn mclBnFp_setInt32(x: *mut Fp, v: i32); - fn mclBnFp_setLittleEndian(x: *mut Fp, buf: *const u8, bufSize: usize) -> i32; - fn mclBnFp_getLittleEndian(buf: *mut u8, bufSize: usize, x: *const Fp) -> i32; - fn mclBnFp_setLittleEndianMod(x: *mut Fp, buf: *const u8, bufSize: usize) -> i32; - fn mclBnFp_setHashOf(x: *mut Fp, buf: *const u8, bufSize: usize) -> i32; - fn mclBnFp_setByCSPRNG(x: *mut Fp); - - fn mclBnFp_add(z: *mut Fp, x: *const Fp, y: *const Fp); - fn mclBnFp_sub(z: *mut Fp, x: *const Fp, y: *const Fp); - fn mclBnFp_neg(y: *mut Fp, x: *const Fp); - - fn mclBnFp_mul(z: *mut Fp, x: *const Fp, y: *const Fp); - fn mclBnFp_div(z: *mut Fp, x: *const Fp, y: *const Fp); - fn mclBnFp_inv(y: *mut Fp, x: *const Fp); - fn mclBnFp_sqr(y: *mut Fp, x: *const Fp); - fn mclBnFp_squareRoot(y: *mut Fp, x: *const Fp) -> i32; - -} - -#[derive(Default, Debug, Clone, Copy)] -#[repr(C)] -pub struct Fp { - pub d: [u64; crate::MCLBN_FP_UNIT_SIZE], -} -impl Fp { - pub fn get_order() -> String { - get_field_order() - } -} -common_impl![Fp, mclBnFp_isEqual, mclBnFp_isZero]; -is_valid_impl![Fp, mclBnFp_isValid]; -serialize_impl![ - Fp, - mclBn_getFpByteSize(), - mclBnFp_serialize, - mclBnFp_deserialize -]; -str_impl![Fp, 1024, mclBnFp_getStr, mclBnFp_setStr]; -int_impl![Fp, mclBnFp_setInt32, mclBnFp_isOne]; -base_field_impl![ - Fp, - mclBnFp_setLittleEndian, - mclBnFp_getLittleEndian, - mclBnFp_setLittleEndianMod, - mclBnFp_setHashOf, - mclBnFp_setByCSPRNG, - mclBnFp_isOdd, - mclBnFp_isNegative, - mclBnFp_squareRoot -]; -add_op_impl![Fp, mclBnFp_add, mclBnFp_sub, mclBnFp_neg]; -field_mul_op_impl![Fp, mclBnFp_mul, mclBnFp_div, mclBnFp_inv, mclBnFp_sqr]; diff --git a/mcl/kzg/src/data_types/fp2.rs b/mcl/kzg/src/data_types/fp2.rs deleted file mode 100644 index 0d4defaa9..000000000 --- a/mcl/kzg/src/data_types/fp2.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::data_types::fp::Fp; -use crate::mcl_methods; -use std::ops::{Add, AddAssign}; -use std::ops::{Div, DivAssign}; -use std::ops::{Mul, MulAssign}; -use std::ops::{Sub, SubAssign}; -use std::os::raw::c_int; - -#[link(name = "mcl", kind = "static")] -#[link(name = "mclbn384_256", kind = "static")] -#[link(name = "stdc++")] -#[allow(non_snake_case)] -extern "C" { - fn mclBnFp2_isEqual(x: *const Fp2, y: *const Fp2) -> i32; - fn mclBnFp2_isZero(x: *const Fp2) -> i32; - - fn mclBnFp2_setStr(x: *mut Fp2, buf: *const u8, bufSize: usize, ioMode: i32) -> c_int; - fn mclBnFp2_getStr(buf: *mut u8, maxBufSize: usize, x: *const Fp2, ioMode: i32) -> usize; - fn mclBnFp2_serialize(buf: *mut u8, maxBufSize: usize, x: *const Fp2) -> usize; - fn mclBnFp2_deserialize(x: *mut Fp2, buf: *const u8, bufSize: usize) -> usize; - - fn mclBnFp2_add(z: *mut Fp2, x: *const Fp2, y: *const Fp2); - fn mclBnFp2_sub(z: *mut Fp2, x: *const Fp2, y: *const Fp2); - fn mclBnFp2_neg(y: *mut Fp2, x: *const Fp2); - - fn mclBnFp2_mul(z: *mut Fp2, x: *const Fp2, y: *const Fp2); - fn mclBnFp2_div(z: *mut Fp2, x: *const Fp2, y: *const Fp2); - fn mclBnFp2_inv(y: *mut Fp2, x: *const Fp2); - fn mclBnFp2_sqr(y: *mut Fp2, x: *const Fp2); - fn mclBnFp2_squareRoot(y: *mut Fp2, x: *const Fp2) -> i32; -} - -#[derive(Default, Debug, Clone, Copy)] -#[repr(C)] -pub struct Fp2 { - pub d: [Fp; 2], -} -common_impl![Fp2, mclBnFp2_isEqual, mclBnFp2_isZero]; -serialize_impl![ - Fp2, - mcl_methods::mclBn_getFpByteSize() * 2, - mclBnFp2_serialize, - mclBnFp2_deserialize -]; -str_impl![Fp2, 1024, mclBnFp2_getStr, mclBnFp2_setStr]; -add_op_impl![Fp2, mclBnFp2_add, mclBnFp2_sub, mclBnFp2_neg]; -field_mul_op_impl![Fp2, mclBnFp2_mul, mclBnFp2_div, mclBnFp2_inv, mclBnFp2_sqr]; -impl Fp2 { - pub fn square_root(y: &mut Fp2, x: &Fp2) -> bool { - unsafe { mclBnFp2_squareRoot(y, x) == 0 } - } -} diff --git a/mcl/kzg/src/data_types/fr.rs b/mcl/kzg/src/data_types/fr.rs deleted file mode 100644 index 5cc78512f..000000000 --- a/mcl/kzg/src/data_types/fr.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::mcl_methods; -use std::ops::{Add, AddAssign}; -use std::ops::{Div, DivAssign}; -use std::ops::{Mul, MulAssign}; -use std::ops::{Sub, SubAssign}; -use std::os::raw::c_int; - -#[link(name = "mcl", kind = "static")] -#[link(name = "mclbn384_256", kind = "static")] -#[link(name = "stdc++")] -#[allow(non_snake_case)] -extern "C" { - fn mclBnFr_isEqual(x: *const Fr, y: *const Fr) -> i32; - fn mclBnFr_isValid(x: *const Fr) -> i32; - fn mclBnFr_isZero(x: *const Fr) -> i32; - fn mclBnFr_isOne(x: *const Fr) -> i32; - fn mclBnFr_isOdd(x: *const Fr) -> i32; - fn mclBnFr_isNegative(x: *const Fr) -> i32; - - fn mclBnFr_setStr(x: *mut Fr, buf: *const u8, bufSize: usize, ioMode: i32) -> c_int; - fn mclBnFr_getStr(buf: *mut u8, maxBufSize: usize, x: *const Fr, ioMode: i32) -> usize; - fn mclBnFr_serialize(buf: *mut u8, maxBufSize: usize, x: *const Fr) -> usize; - fn mclBnFr_deserialize(x: *mut Fr, buf: *const u8, bufSize: usize) -> usize; - - fn mclBnFr_setInt32(x: *mut Fr, v: i32); - fn mclBnFr_setLittleEndian(x: *mut Fr, buf: *const u8, bufSize: usize) -> i32; - fn mclBnFr_getLittleEndian(buf: *mut u8, bufSize: usize, x: *const Fr) -> i32; - fn mclBnFr_setLittleEndianMod(x: *mut Fr, buf: *const u8, bufSize: usize) -> i32; - fn mclBnFr_setHashOf(x: *mut Fr, buf: *const u8, bufSize: usize) -> i32; - fn mclBnFr_setByCSPRNG(x: *mut Fr); - - fn mclBnFr_add(z: *mut Fr, x: *const Fr, y: *const Fr); - fn mclBnFr_sub(z: *mut Fr, x: *const Fr, y: *const Fr); - fn mclBnFr_neg(y: *mut Fr, x: *const Fr); - - fn mclBnFr_mul(z: *mut Fr, x: *const Fr, y: *const Fr); - fn mclBnFr_div(z: *mut Fr, x: *const Fr, y: *const Fr); - fn mclBnFr_inv(y: *mut Fr, x: *const Fr); - fn mclBnFr_sqr(y: *mut Fr, x: *const Fr); - fn mclBnFr_squareRoot(y: *mut Fr, x: *const Fr) -> i32; -} - -#[derive(Default, Debug, Clone, Copy)] -#[repr(C)] -pub struct Fr { - pub d: [u64; crate::MCLBN_FR_UNIT_SIZE], -} - -pub struct U2516([u64; 4]); - -impl Fr { - pub fn get_order() -> String { - mcl_methods::get_curve_order() - } - - pub fn pow(&self, n: usize) -> Self { - if n == 0 { - return Self::one(); - } - let mut res = *self; - for _ in 1..n { - res = res * *self; - } - res - } - - pub fn inverse(&self) -> Self { - let mut res = Fr::zero(); - Fr::inv(&mut res, self); - res - } - - pub fn from_u64_arr(u: &[u64; 4]) -> Self { - let mut arr = [0u8; 32]; - for i in 0..4 { - arr[i * 8..i * 8 + 8].copy_from_slice(&u[i].to_le_bytes()); - } - Fr::from_bytes(&arr).unwrap() - } - - pub fn from_bytes(bytes: &[u8]) -> Result { - let mut t = Fr::default(); - if !t.set_little_endian_mod(bytes) { - return Err("Invalid scalar".to_string()); - } - Ok(t) - } - - pub fn to_bytes(fr: &Self) -> [u8; 32] { - let mut buf = [0u8; 32]; - assert!(fr.get_little_endian(&mut buf)); - buf - } - - pub fn to_u64_arr(&self) -> [u64; 4] { - let v: Vec = Fr::to_bytes(self) - .chunks(8) - .map(|ch| u64::from_le_bytes(ch.try_into().unwrap())) - .collect(); - - v.try_into().unwrap() - } -} -common_impl![Fr, mclBnFr_isEqual, mclBnFr_isZero]; -is_valid_impl![Fr, mclBnFr_isValid]; -serialize_impl![ - Fr, - mcl_methods::mclBn_getFrByteSize(), - mclBnFr_serialize, - mclBnFr_deserialize -]; -str_impl![Fr, 1024, mclBnFr_getStr, mclBnFr_setStr]; -int_impl![Fr, mclBnFr_setInt32, mclBnFr_isOne]; -base_field_impl![ - Fr, - mclBnFr_setLittleEndian, - mclBnFr_getLittleEndian, - mclBnFr_setLittleEndianMod, - mclBnFr_setHashOf, - mclBnFr_setByCSPRNG, - mclBnFr_isOdd, - mclBnFr_isNegative, - mclBnFr_squareRoot -]; -add_op_impl![Fr, mclBnFr_add, mclBnFr_sub, mclBnFr_neg]; -field_mul_op_impl![Fr, mclBnFr_mul, mclBnFr_div, mclBnFr_inv, mclBnFr_sqr]; diff --git a/mcl/kzg/src/data_types/g1.rs b/mcl/kzg/src/data_types/g1.rs deleted file mode 100644 index e0f366142..000000000 --- a/mcl/kzg/src/data_types/g1.rs +++ /dev/null @@ -1,104 +0,0 @@ -use crate::data_types::fp::Fp; -use crate::data_types::fr::Fr; -use crate::mcl_methods; -use crate::utilities::arr64_6_to_g1_sum; -#[cfg(feature = "parallel")] -use kzg::G1 as _; -use std::ops::{Add, AddAssign}; -use std::ops::{Sub, SubAssign}; -use std::os::raw::c_int; - -#[cfg(feature = "parallel")] -use rayon::prelude::*; - -#[link(name = "mcl", kind = "static")] -#[link(name = "mclbn384_256", kind = "static")] -#[link(name = "stdc++")] -#[allow(non_snake_case)] -extern "C" { - pub fn mclBnG1_isEqual(x: *const G1, y: *const G1) -> i32; - pub fn mclBnG1_isValid(x: *const G1) -> i32; - pub fn mclBnG1_isZero(x: *const G1) -> i32; - pub fn mclBnG1_isValidOrder(x: *const G1) -> i32; - - pub fn mclBnG1_setStr(x: *mut G1, buf: *const u8, bufSize: usize, ioMode: i32) -> c_int; - pub fn mclBnG1_getStr(buf: *mut u8, maxBufSize: usize, x: *const G1, ioMode: i32) -> usize; - pub fn mclBnG1_serialize(buf: *mut u8, maxBufSize: usize, x: *const G1) -> usize; - pub fn mclBnG1_deserialize(x: *mut G1, buf: *const u8, bufSize: usize) -> usize; - pub fn mclBnG1_mulVec(x: *mut G1, vec1: *const G1, vec2: *const Fr, bufSize: usize); - - pub fn mclBnG1_add(z: *mut G1, x: *const G1, y: *const G1); - pub fn mclBnG1_sub(z: *mut G1, x: *const G1, y: *const G1); - pub fn mclBnG1_neg(y: *mut G1, x: *const G1); - - pub fn mclBnG1_dbl(y: *mut G1, x: *const G1); - pub fn mclBnG1_mul(z: *mut G1, x: *const G1, y: *const Fr); - pub fn mclBnG1_normalize(y: *mut G1, x: *const G1); - pub fn mclBnG1_hashAndMapTo(x: *mut G1, buf: *const u8, bufSize: usize) -> c_int; -} - -pub fn g1_linear_combination(out: &mut G1, points: &[G1], scalars: &[Fr], len: usize) { - #[cfg(feature = "parallel")] - { - *out = (0..len) - .into_par_iter() - .map(|i| points[i] * &scalars[i]) - .reduce(G1::default, |mut acc, tmp| acc.add_or_dbl(&tmp)); - } - - #[cfg(not(feature = "parallel"))] - { - unsafe { mclBnG1_mulVec(out, points.as_ptr(), scalars.as_ptr(), len) } - } -} - -pub fn is_valid_order(g1: &G1) -> bool { - unsafe { mclBnG1_isValidOrder(g1) == 1 } -} - -#[derive(Default, Debug, Clone, Copy)] -#[repr(C)] -pub struct G1 { - pub x: Fp, - pub y: Fp, - pub z: Fp, -} -common_impl![G1, mclBnG1_isEqual, mclBnG1_isZero]; -is_valid_impl![G1, mclBnG1_isValid]; -serialize_impl![ - G1, - mcl_methods::mclBn_getFpByteSize(), - mclBnG1_serialize, - mclBnG1_deserialize -]; -str_impl![G1, 1024, mclBnG1_getStr, mclBnG1_setStr]; -add_op_impl![G1, mclBnG1_add, mclBnG1_sub, mclBnG1_neg]; -ec_impl![ - G1, - mclBnG1_dbl, - mclBnG1_mul, - mclBnG1_normalize, - mclBnG1_hashAndMapTo -]; - -impl G1 { - pub fn from_arr_64(u: &[[u64; 6]; 3]) -> G1 { - let mut g1 = G1::default(); - g1.x.set_str(&arr64_6_to_g1_sum(&u[0]).to_string(), 10); - g1.y.set_str(&arr64_6_to_g1_sum(&u[1]).to_string(), 10); - g1.z.set_str(&arr64_6_to_g1_sum(&u[2]).to_string(), 10); - g1 - } - - pub const G1_IDENTITY: G1 = G1 { - x: Fp { - d: [0, 0, 0, 0, 0, 0], - }, - y: Fp { - d: [0, 0, 0, 0, 0, 0], - }, - z: Fp { - d: [0, 0, 0, 0, 0, 0], - }, - }; -} diff --git a/mcl/kzg/src/data_types/g2.rs b/mcl/kzg/src/data_types/g2.rs deleted file mode 100644 index d4c7226c9..000000000 --- a/mcl/kzg/src/data_types/g2.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::data_types::fp::Fp; -use crate::data_types::fp2::Fp2; -use crate::data_types::fr::Fr; -use crate::mcl_methods; -use std::ops::{Add, AddAssign}; -use std::ops::{Sub, SubAssign}; -use std::os::raw::c_int; - -#[link(name = "mcl", kind = "static")] -#[link(name = "mclbn384_256", kind = "static")] -#[link(name = "stdc++")] -#[allow(non_snake_case)] -extern "C" { - fn mclBnG2_isEqual(x: *const G2, y: *const G2) -> i32; - fn mclBnG2_isValid(x: *const G2) -> i32; - fn mclBnG2_isZero(x: *const G2) -> i32; - - fn mclBnG2_setStr(x: *mut G2, buf: *const u8, bufSize: usize, ioMode: i32) -> c_int; - fn mclBnG2_getStr(buf: *mut u8, maxBufSize: usize, x: *const G2, ioMode: i32) -> usize; - fn mclBnG2_serialize(buf: *mut u8, maxBufSize: usize, x: *const G2) -> usize; - fn mclBnG2_deserialize(x: *mut G2, buf: *const u8, bufSize: usize) -> usize; - - fn mclBnG2_add(z: *mut G2, x: *const G2, y: *const G2); - fn mclBnG2_sub(z: *mut G2, x: *const G2, y: *const G2); - fn mclBnG2_neg(y: *mut G2, x: *const G2); - - fn mclBnG2_dbl(y: *mut G2, x: *const G2); - fn mclBnG2_mul(z: *mut G2, x: *const G2, y: *const Fr); - fn mclBnG2_normalize(y: *mut G2, x: *const G2); - fn mclBnG2_hashAndMapTo(x: *mut G2, buf: *const u8, bufSize: usize) -> c_int; -} - -#[derive(Default, Debug, Clone, Copy)] -#[repr(C)] -pub struct G2 { - pub x: Fp2, - pub y: Fp2, - pub z: Fp2, -} -common_impl![G2, mclBnG2_isEqual, mclBnG2_isZero]; -is_valid_impl![G2, mclBnG2_isValid]; -serialize_impl![ - G2, - mcl_methods::mclBn_getFpByteSize() * 2, - mclBnG2_serialize, - mclBnG2_deserialize -]; -str_impl![G2, 1024, mclBnG2_getStr, mclBnG2_setStr]; -add_op_impl![G2, mclBnG2_add, mclBnG2_sub, mclBnG2_neg]; -ec_impl![ - G2, - mclBnG2_dbl, - mclBnG2_mul, - mclBnG2_normalize, - mclBnG2_hashAndMapTo -]; - -impl G2 { - pub const G2_NEGATIVE_GENERATOR: G2 = G2 { - x: Fp2 { - d: [ - Fp { - d: [ - 0xf5f28fa202940a10, - 0xb3f5fb2687b4961a, - 0xa1a893b53e2ae580, - 0x9894999d1a3caee9, - 0x6f67b7631863366b, - 0x058191924350bcd7, - ], - }, - Fp { - d: [ - 0xa5a9c0759e23f606, - 0xaaa0c59dbccd60c3, - 0x3bb17e18e2867806, - 0x1b1ab6cc8541b367, - 0xc2b6ed0ef2158547, - 0x11922a097360edf3, - ], - }, - ], - }, - y: Fp2 { - d: [ - Fp { - d: [ - 0x6d8bf5079fb65e61, - 0xc52f05df531d63a5, - 0x7f4a4d344ca692c9, - 0xa887959b8577c95f, - 0x4347fe40525c8734, - 0x197d145bbaff0bb5, - ], - }, - Fp { - d: [ - 0x0c3e036d209afa4e, - 0x0601d8f4863f9e23, - 0xe0832636bacc0a84, - 0xeb2def362a476f84, - 0x64044f659f0ee1e9, - 0x0ed54f48d5a1caa7, - ], - }, - ], - }, - z: Fp2 { - d: [ - Fp { - d: [ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, - ], - }, - Fp { - d: [ - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000, - ], - }, - ], - }, - }; -} diff --git a/mcl/kzg/src/data_types/gt.rs b/mcl/kzg/src/data_types/gt.rs deleted file mode 100644 index aea70b935..000000000 --- a/mcl/kzg/src/data_types/gt.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::data_types::fp::Fp; -use crate::data_types::fr::Fr; -use crate::mcl_methods; -use std::ops::{Add, AddAssign}; -use std::ops::{Div, DivAssign}; -use std::ops::{Mul, MulAssign}; -use std::ops::{Sub, SubAssign}; -use std::os::raw::c_int; - -#[link(name = "mcl", kind = "static")] -#[link(name = "mclbn384_256", kind = "static")] -#[link(name = "stdc++")] -#[allow(non_snake_case)] -extern "C" { - fn mclBnGT_isEqual(x: *const GT, y: *const GT) -> i32; - fn mclBnGT_isZero(x: *const GT) -> i32; - fn mclBnGT_isOne(x: *const GT) -> i32; - - fn mclBnGT_setStr(x: *mut GT, buf: *const u8, bufSize: usize, ioMode: i32) -> c_int; - fn mclBnGT_getStr(buf: *mut u8, maxBufSize: usize, x: *const GT, ioMode: i32) -> usize; - fn mclBnGT_serialize(buf: *mut u8, maxBufSize: usize, x: *const GT) -> usize; - fn mclBnGT_deserialize(x: *mut GT, buf: *const u8, bufSize: usize) -> usize; - - fn mclBnGT_setInt32(x: *mut GT, v: i32); - - fn mclBnGT_add(z: *mut GT, x: *const GT, y: *const GT); - fn mclBnGT_sub(z: *mut GT, x: *const GT, y: *const GT); - fn mclBnGT_neg(y: *mut GT, x: *const GT); - - fn mclBnGT_mul(z: *mut GT, x: *const GT, y: *const GT); - fn mclBnGT_div(z: *mut GT, x: *const GT, y: *const GT); - fn mclBnGT_inv(y: *mut GT, x: *const GT); - fn mclBnGT_sqr(y: *mut GT, x: *const GT); - - fn mclBnGT_pow(z: *mut GT, x: *const GT, y: *const Fr); -} - -#[derive(Default, Debug, Clone)] -#[repr(C)] -pub struct GT { - pub d: [Fp; 12], -} -common_impl![GT, mclBnGT_isEqual, mclBnGT_isZero]; -serialize_impl![ - GT, - mcl_methods::mclBn_getFpByteSize() * 12, - mclBnGT_serialize, - mclBnGT_deserialize -]; -str_impl![GT, 1024, mclBnGT_getStr, mclBnGT_setStr]; -int_impl![GT, mclBnGT_setInt32, mclBnGT_isOne]; -add_op_impl![GT, mclBnGT_add, mclBnGT_sub, mclBnGT_neg]; -field_mul_op_impl![GT, mclBnGT_mul, mclBnGT_div, mclBnGT_inv, mclBnGT_sqr]; -impl GT { - pub fn pow(z: &mut GT, x: >, y: &Fr) { - unsafe { mclBnGT_pow(z, x, y) } - } -} diff --git a/mcl/kzg/src/eip_4844.rs b/mcl/kzg/src/eip_4844.rs deleted file mode 100644 index 77d285496..000000000 --- a/mcl/kzg/src/eip_4844.rs +++ /dev/null @@ -1,545 +0,0 @@ -use crate::data_types::g1::g1_linear_combination; -use crate::data_types::{fr::*, g1::G1, g2::G2}; -use crate::fk20_fft::*; -use crate::kzg10::{Curve, Polynomial}; -use crate::kzg_settings::KZGSettings; -use kzg::common_utils::reverse_bit_order; -use kzg::eip_4844::{ - bytes_of_uint64, hash, load_trusted_setup_string, BYTES_PER_BLOB, BYTES_PER_COMMITMENT, - BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, BYTES_PER_PROOF, CHALLENGE_INPUT_SIZE, - FIAT_SHAMIR_PROTOCOL_DOMAIN, FIELD_ELEMENTS_PER_BLOB, RANDOM_CHALLENGE_KZG_BATCH_DOMAIN, - TRUSTED_SETUP_NUM_G2_POINTS, -}; -use kzg::{cfg_into_iter, G1 as _, G2 as _}; -use std::convert::TryInto; -use std::fs::File; -use std::io::Read; -use std::usize; - -#[cfg(feature = "parallel")] -use rayon::prelude::*; - -pub fn hash_to_bls_field(x: &[u8; BYTES_PER_FIELD_ELEMENT]) -> Fr { - Fr::from_bytes(x).unwrap() -} - -#[allow(clippy::useless_conversion)] -pub fn bytes_to_blob(bytes: &[u8]) -> Result, String> { - if bytes.len() != BYTES_PER_BLOB { - return Err(format!( - "Invalid byte length. Expected {} got {}", - BYTES_PER_BLOB, - bytes.len(), - )); - } - - bytes - .chunks(BYTES_PER_FIELD_ELEMENT) - .map(|chunk| { - chunk - .try_into() - .map_err(|_| "Chunked into incorrect number of bytes".to_string()) - .and_then(Fr::from_bytes) - }) - .collect() -} - -#[allow(clippy::useless_conversion)] -pub fn load_trusted_setup_from_bytes(g1_bytes: &[u8], g2_bytes: &[u8]) -> KZGSettings { - let num_g1_points = g1_bytes.len() / BYTES_PER_G1; - - assert_eq!(num_g1_points, FIELD_ELEMENTS_PER_BLOB); - assert_eq!(g2_bytes.len() / BYTES_PER_G2, TRUSTED_SETUP_NUM_G2_POINTS); - - let g1_projectives: Vec = g1_bytes - .chunks(BYTES_PER_G1) - .map(|chunk| { - G1::from_bytes( - chunk - .try_into() - .expect("Chunked into incorrect number of bytes"), - ) - .unwrap() - }) - .collect(); - - let g2_values: Vec = g2_bytes - .chunks(BYTES_PER_G2) - .map(|chunk| { - G2::from_bytes( - chunk - .try_into() - .expect("Chunked into incorrect number of bytes"), - ) - .unwrap() - }) - .collect(); - - let mut max_scale: usize = 0; - while (1 << max_scale) < num_g1_points { - max_scale += 1; - } - - let fs = FFTSettings::new(max_scale as u8); - let mut g1_values = fs.fft_g1_inv(&g1_projectives).unwrap(); - reverse_bit_order(&mut g1_values); - - KZGSettings { - fft_settings: fs, - curve: Curve { - g1_gen: G1::gen(), - g2_gen: G2::gen(), - g1_points: g1_values, - g2_points: g2_values, - }, - } -} - -pub fn load_trusted_setup(filepath: &str) -> KZGSettings { - let mut file = File::open(filepath).expect("Unable to open file"); - let mut contents = String::new(); - file.read_to_string(&mut contents) - .expect("Unable to read file"); - - let (g1_bytes, g2_bytes) = load_trusted_setup_string(&contents); - load_trusted_setup_from_bytes(g1_bytes.as_slice(), g2_bytes.as_slice()) -} - -fn g1_lincomb(points: &[G1], scalars: &[Fr], length: usize) -> G1 { - let mut out = G1::default(); - g1_linear_combination(&mut out, points, scalars, length); - out -} - -pub fn blob_to_kzg_commitment(blob: &[Fr], s: &KZGSettings) -> G1 { - let p = blob_to_polynomial(blob); - poly_to_kzg_commitment(&p, s) -} - -pub fn verify_kzg_proof( - commitment: &G1, - z: &Fr, - y: &Fr, - proof: &G1, - ks: &KZGSettings, -) -> Result { - if !commitment.is_valid() { - return Err("Invalid commitment".to_string()); - } - if !proof.is_valid() { - return Err("Invalid proof".to_string()); - } - - Ok(ks.curve.is_proof_valid(commitment, proof, z, y)) -} - -pub fn verify_kzg_proof_batch( - commitments_g1: &[G1], - zs_fr: &[Fr], - ys_fr: &[Fr], - proofs_g1: &[G1], - ts: &KZGSettings, -) -> bool { - let n = commitments_g1.len(); - let mut c_minus_y: Vec = Vec::new(); - let mut r_times_z: Vec = Vec::new(); - - // Compute the random lincomb challenges - let r_powers = compute_r_powers(commitments_g1, zs_fr, ys_fr, proofs_g1); - - // Compute \sum r^i * Proof_i - let proof_lincomb = g1_lincomb(proofs_g1, &r_powers, n); - - for i in 0..n { - // Get [y_i] - let ys_encrypted = &G1::gen() * &ys_fr[i]; - // Get C_i - [y_i] - c_minus_y.push(commitments_g1[i] - ys_encrypted); - // Get r^i * z_i - r_times_z.push(r_powers[i] * zs_fr[i]); - } - - // Get \sum r^i z_i Proof_i - let proof_z_lincomb = g1_lincomb(proofs_g1, &r_times_z, n); - // Get \sum r^i (C_i - [y_i]) - let mut c_minus_y_lincomb = g1_lincomb(&c_minus_y, &r_powers, n); - - // Get C_minus_y_lincomb + proof_z_lincomb - let rhs_g1 = c_minus_y_lincomb.add_or_dbl(&proof_z_lincomb); - - // Do the pairing check! - Curve::verify_pairing(&proof_lincomb, &ts.curve.g2_points[1], &rhs_g1, &G2::gen()) -} - -pub fn compute_kzg_proof(blob: &[Fr], z: &Fr, s: &KZGSettings) -> (G1, Fr) { - assert_eq!(blob.len(), FIELD_ELEMENTS_PER_BLOB); - - let polynomial = blob_to_polynomial(blob); - let y = evaluate_polynomial_in_evaluation_form(&polynomial, z, s); - - let mut tmp: Fr; - let roots_of_unity: &Vec = &s.fft_settings.roots_of_unity; - - let mut m = 0; - let mut q = Polynomial::new(FIELD_ELEMENTS_PER_BLOB); - - let mut inverses_in: Vec = vec![Fr::default(); FIELD_ELEMENTS_PER_BLOB]; - let mut inverses: Vec = vec![Fr::default(); FIELD_ELEMENTS_PER_BLOB]; - - for i in 0..FIELD_ELEMENTS_PER_BLOB { - if z == &roots_of_unity[i] { - // We are asked to compute a KZG proof inside the domain - m = i + 1; - inverses_in[i] = Fr::one(); - continue; - } - // (p_i - y) / (ω_i - z) - q.coeffs[i] = polynomial.coeffs[i] - y; - inverses_in[i] = &roots_of_unity[i] - z; - } - - fr_batch_inv(&mut inverses, &inverses_in, FIELD_ELEMENTS_PER_BLOB); - - for (i, inverse) in inverses.iter().enumerate().take(FIELD_ELEMENTS_PER_BLOB) { - q.coeffs[i] = &q.coeffs[i] * inverse; - } - - if m != 0 { - // ω_{m-1} == z - m -= 1; - q.coeffs[m] = Fr::zero(); - for i in 0..FIELD_ELEMENTS_PER_BLOB { - if i == m { - continue; - } - // Build denominator: z * (z - ω_i) - tmp = z - &roots_of_unity[i]; - inverses_in[i] = &tmp * z; - } - - fr_batch_inv(&mut inverses, &inverses_in, FIELD_ELEMENTS_PER_BLOB); - - for i in 0..FIELD_ELEMENTS_PER_BLOB { - if i == m { - continue; - } - // Build numerator: ω_i * (p_i - y) - tmp = polynomial.coeffs[i] - y; - tmp = tmp * roots_of_unity[i]; - // Do the division: (p_i - y) * ω_i / (z * (z - ω_i)) - tmp = tmp * inverses[i]; - q.coeffs[i] = q.coeffs[i] + tmp; - } - } - - let proof = g1_lincomb( - &s.curve.g1_points, - q.coeffs.as_slice(), - FIELD_ELEMENTS_PER_BLOB, - ); - (proof, y) -} - -pub fn evaluate_polynomial_in_evaluation_form(p: &Polynomial, x: &Fr, s: &KZGSettings) -> Fr { - assert_eq!(p.coeffs.len(), FIELD_ELEMENTS_PER_BLOB); - - let roots_of_unity: &Vec = &s.fft_settings.roots_of_unity; - let mut inverses_in = vec![Fr::default(); FIELD_ELEMENTS_PER_BLOB]; - let mut inverses = vec![Fr::default(); FIELD_ELEMENTS_PER_BLOB]; - - for i in 0..FIELD_ELEMENTS_PER_BLOB { - if *x == roots_of_unity[i] { - return p.coeffs[i]; - } - inverses_in[i] = x - &roots_of_unity[i]; - } - - fr_batch_inv( - inverses.as_mut_slice(), - inverses_in.as_slice(), - FIELD_ELEMENTS_PER_BLOB, - ); - - let mut tmp: Fr; - let mut out = Fr::zero(); - - for i in 0..FIELD_ELEMENTS_PER_BLOB { - tmp = inverses[i] * roots_of_unity[i]; - tmp = tmp * p.coeffs[i]; - out = out + tmp; - } - - let arr: [u64; 4] = [FIELD_ELEMENTS_PER_BLOB as u64, 0, 0, 0]; - tmp = Fr::from_u64_arr(&arr); - out = out / tmp; - tmp = x.pow(FIELD_ELEMENTS_PER_BLOB); - tmp = tmp - Fr::one(); - out = out * tmp; - out -} - -pub fn compute_powers(base: &Fr, num_powers: usize) -> Vec { - let mut powers: Vec = vec![Fr::default(); num_powers]; - if num_powers == 0 { - return powers; - } - powers[0] = Fr::one(); - for i in 1..num_powers { - powers[i] = &powers[i - 1] * base; - } - powers -} - -fn fr_batch_inv(out: &mut [Fr], a: &[Fr], len: usize) { - assert!(len > 0); - - let mut accumulator = Fr::one(); - - for i in 0..len { - out[i] = accumulator; - accumulator = accumulator * a[i]; - } - - accumulator = accumulator.inverse(); - - for i in (0..len).rev() { - out[i] = out[i] * accumulator; - accumulator = accumulator * a[i]; - } -} - -pub fn compute_blob_kzg_proof(blob: &[Fr], commitment: &G1, s: &KZGSettings) -> Result { - if !commitment.is_valid() { - return Err("Invalid commitment".to_string()); - } - - let evaluation_challenge_fr = compute_challenge(blob, commitment); - let (proof, _) = compute_kzg_proof(blob, &evaluation_challenge_fr, s); - Ok(proof) -} - -pub fn verify_blob_kzg_proof( - blob: &[Fr], - commitment_g1: &G1, - proof_g1: &G1, - ts: &KZGSettings, -) -> Result { - if !commitment_g1.is_valid() { - return Err("Invalid commitment".to_string()); - } - if !proof_g1.is_valid() { - return Err("Invalid proof".to_string()); - } - - let polynomial = blob_to_polynomial(blob); - let evaluation_challenge_fr = compute_challenge(blob, commitment_g1); - let y_fr = evaluate_polynomial_in_evaluation_form(&polynomial, &evaluation_challenge_fr, ts); - verify_kzg_proof(commitment_g1, &evaluation_challenge_fr, &y_fr, proof_g1, ts) -} - -fn compute_challenges_and_evaluate_polynomial( - blobs: &[Vec], - commitments_g1: &[G1], - ts: &KZGSettings, -) -> (Vec, Vec) { - let mut evaluation_challenges_fr = Vec::new(); - let mut ys_fr = Vec::new(); - - for i in 0..blobs.len() { - let polynomial = blob_to_polynomial(&blobs[i]); - let evaluation_challenge_fr = compute_challenge(&blobs[i], &commitments_g1[i]); - let y_fr = - evaluate_polynomial_in_evaluation_form(&polynomial, &evaluation_challenge_fr, ts); - - evaluation_challenges_fr.push(evaluation_challenge_fr); - ys_fr.push(y_fr); - } - - (evaluation_challenges_fr, ys_fr) -} - -fn validate_batched_input(commitments: &[G1], proofs: &[G1]) -> Result<(), String> { - let invalid_commitment = cfg_into_iter!(commitments).any(|&commitment| !commitment.is_valid()); - let invalid_proof = cfg_into_iter!(proofs).any(|&proof| !proof.is_valid()); - - if invalid_commitment { - return Err("Invalid commitment".to_string()); - } - if invalid_proof { - return Err("Invalid proof".to_string()); - } - - Ok(()) -} - -pub fn verify_blob_kzg_proof_batch( - blobs: &[Vec], - commitments_g1: &[G1], - proofs_g1: &[G1], - ts: &KZGSettings, -) -> Result { - // Exit early if we are given zero blobs - if blobs.is_empty() { - return Ok(true); - } - - // For a single blob, just do a regular single verification - if blobs.len() == 1 { - return verify_blob_kzg_proof(&blobs[0], &commitments_g1[0], &proofs_g1[0], ts); - } - - if blobs.len() != commitments_g1.len() || blobs.len() != proofs_g1.len() { - return Err("Invalid amount of arguments".to_string()); - } - - #[cfg(feature = "parallel")] - { - let num_blobs = blobs.len(); - let num_cores = num_cpus::get_physical(); - - return if num_blobs > num_cores { - validate_batched_input(commitments_g1, proofs_g1)?; - - // Process blobs in parallel subgroups - let blobs_per_group = num_blobs / num_cores; - - Ok(blobs - .par_chunks(blobs_per_group) - .enumerate() - .all(|(i, blob_group)| { - let num_blobs_in_group = blob_group.len(); - let commitment_group = &commitments_g1 - [blobs_per_group * i..blobs_per_group * i + num_blobs_in_group]; - let proof_group = - &proofs_g1[blobs_per_group * i..blobs_per_group * i + num_blobs_in_group]; - let (evaluation_challenges_fr, ys_fr) = - compute_challenges_and_evaluate_polynomial( - blob_group, - commitment_group, - ts, - ); - - verify_kzg_proof_batch( - commitment_group, - &evaluation_challenges_fr, - &ys_fr, - proof_group, - ts, - ) - })) - } else { - // Each group contains either one or zero blobs, so iterate - // over the single blob verification function in parallel - Ok((blobs, commitments_g1, proofs_g1).into_par_iter().all( - |(blob, commitment, proof)| { - verify_blob_kzg_proof(blob, commitment, proof, ts).unwrap() - }, - )) - }; - } - - #[cfg(not(feature = "parallel"))] - { - validate_batched_input(commitments_g1, proofs_g1)?; - let (evaluation_challenges_fr, ys_fr) = - compute_challenges_and_evaluate_polynomial(blobs, commitments_g1, ts); - - Ok(verify_kzg_proof_batch( - commitments_g1, - &evaluation_challenges_fr, - &ys_fr, - proofs_g1, - ts, - )) - } -} - -fn compute_challenge(blob: &[Fr], commitment: &G1) -> Fr { - let mut bytes: Vec = vec![0; CHALLENGE_INPUT_SIZE]; - - // Copy domain separator - bytes[..16].copy_from_slice(&FIAT_SHAMIR_PROTOCOL_DOMAIN); - bytes_of_uint64(&mut bytes[16..24], FIELD_ELEMENTS_PER_BLOB as u64); - // Set all other bytes of this 16-byte (little-endian) field to zero - bytes_of_uint64(&mut bytes[24..32], 0); - - // Copy blob - for i in 0..blob.len() { - let v = Fr::to_bytes(&blob[i]); - bytes[(32 + i * BYTES_PER_FIELD_ELEMENT)..(32 + (i + 1) * BYTES_PER_FIELD_ELEMENT)] - .copy_from_slice(&v); - } - - // Copy commitment - let v = commitment.to_bytes(); - for i in 0..v.len() { - bytes[32 + BYTES_PER_BLOB + i] = v[i]; - } - - // Now let's create the challenge! - let eval_challenge = hash(&bytes); - hash_to_bls_field(&eval_challenge) -} - -fn compute_r_powers( - commitments_g1: &[G1], - zs_fr: &[Fr], - ys_fr: &[Fr], - proofs_g1: &[G1], -) -> Vec { - let n = commitments_g1.len(); - let input_size = - 32 + n * (BYTES_PER_COMMITMENT + 2 * BYTES_PER_FIELD_ELEMENT + BYTES_PER_PROOF); - - #[allow(unused_assignments)] - let mut offset = 0; - let mut bytes: Vec = vec![0; input_size]; - - // Copy domain separator - bytes[..16].copy_from_slice(&RANDOM_CHALLENGE_KZG_BATCH_DOMAIN); - bytes_of_uint64(&mut bytes[16..24], FIELD_ELEMENTS_PER_BLOB as u64); - bytes_of_uint64(&mut bytes[24..32], n as u64); - offset = 32; - - for i in 0..n { - // Copy commitment - let v = commitments_g1[i].to_bytes(); - bytes[offset..(v.len() + offset)].copy_from_slice(&v[..]); - offset += BYTES_PER_COMMITMENT; - - // Copy evaluation challenge - let v = Fr::to_bytes(&zs_fr[i]); - bytes[offset..(v.len() + offset)].copy_from_slice(&v[..]); - offset += BYTES_PER_FIELD_ELEMENT; - - // Copy polynomial's evaluation value - let v = Fr::to_bytes(&ys_fr[i]); - bytes[offset..(v.len() + offset)].copy_from_slice(&v[..]); - offset += BYTES_PER_FIELD_ELEMENT; - - // Copy proof - let v = proofs_g1[i].to_bytes(); - bytes[offset..(v.len() + offset)].copy_from_slice(&v[..]); - offset += BYTES_PER_PROOF; - } - - // Make sure we wrote the entire buffer - assert_eq!(offset, input_size); - - // Now let's create the challenge! - let eval_challenge = hash(&bytes); - let r = hash_to_bls_field(&eval_challenge); - compute_powers(&r, n) -} - -pub fn blob_to_polynomial(blob: &[Fr]) -> Polynomial { - assert_eq!(blob.len(), FIELD_ELEMENTS_PER_BLOB); - let mut p = Polynomial::new(FIELD_ELEMENTS_PER_BLOB); - p.coeffs = blob.to_vec(); - p -} - -fn poly_to_kzg_commitment(p: &Polynomial, s: &KZGSettings) -> G1 { - assert_eq!(p.coeffs.len(), FIELD_ELEMENTS_PER_BLOB); - g1_lincomb(&s.curve.g1_points, &p.coeffs, FIELD_ELEMENTS_PER_BLOB) -} diff --git a/mcl/kzg/src/fk20_fft.rs b/mcl/kzg/src/fk20_fft.rs deleted file mode 100644 index 9f03c5cf8..000000000 --- a/mcl/kzg/src/fk20_fft.rs +++ /dev/null @@ -1,705 +0,0 @@ -use kzg::common_utils::{is_power_of_2, next_pow_of_2, reverse_bit_order}; - -use crate::data_types::{fp::*, fr::*, g1::*}; -use std::iter; - -// MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513 -// PRIMITIVE_ROOT = 5 -// [pow(PRIMITIVE_ROOT, (MODULUS - 1) // (2**i), MODULUS) for i in range(32)] -// TODO: gen dynamically? -pub const SCALE_2_ROOT_OF_UNITY_PR5_STRINGS: [&str; 32] = [ - "1", - "52435875175126190479447740508185965837690552500527637822603658699938581184512", - "3465144826073652318776269530687742778270252468765361963008", - "23674694431658770659612952115660802947967373701506253797663184111817857449850", - "14788168760825820622209131888203028446852016562542525606630160374691593895118", - "36581797046584068049060372878520385032448812009597153775348195406694427778894", - "31519469946562159605140591558550197856588417350474800936898404023113662197331", - "47309214877430199588914062438791732591241783999377560080318349803002842391998", - "36007022166693598376559747923784822035233416720563672082740011604939309541707", - "4214636447306890335450803789410475782380792963881561516561680164772024173390", - "22781213702924172180523978385542388841346373992886390990881355510284839737428", - "49307615728544765012166121802278658070711169839041683575071795236746050763237", - "39033254847818212395286706435128746857159659164139250548781411570340225835782", - "32731401973776920074999878620293785439674386180695720638377027142500196583783", - "39072540533732477250409069030641316533649120504872707460480262653418090977761", - "22872204467218851938836547481240843888453165451755431061227190987689039608686", - "15076889834420168339092859836519192632846122361203618639585008852351569017005", - "15495926509001846844474268026226183818445427694968626800913907911890390421264", - "20439484849038267462774237595151440867617792718791690563928621375157525968123", - "37115000097562964541269718788523040559386243094666416358585267518228781043101", - "1755840822790712607783180844474754741366353396308200820563736496551326485835", - "32468834368094611004052562760214251466632493208153926274007662173556188291130", - "4859563557044021881916617240989566298388494151979623102977292742331120628579", - "52167942466760591552294394977846462646742207006759917080697723404762651336366", - "18596002123094854211120822350746157678791770803088570110573239418060655130524", - "734830308204920577628633053915970695663549910788964686411700880930222744862", - "4541622677469846713471916119560591929733417256448031920623614406126544048514", - "15932505959375582308231798849995567447410469395474322018100309999481287547373", - "37480612446576615530266821837655054090426372233228960378061628060638903214217", - "5660829372603820951332104046316074966592589311213397907344198301300676239643", - "20094891866007995289136270587723853997043774683345353712639419774914899074390", - "34070893824967080313820779135880760772780807222436853681508667398599787661631", -]; - -pub const SCALE_2_ROOT_OF_UNITY_PR7_STRINGS: [&str; 32] = [ - "1", - /* k=1 r=2 */ - "52435875175126190479447740508185965837690552500527637822603658699938581184512", - /* k=2 r=4 */ - "3465144826073652318776269530687742778270252468765361963008", - /* k=3 r=8 */ - "23674694431658770659612952115660802947967373701506253797663184111817857449850", - /* k=4 r=16 */ - "14788168760825820622209131888203028446852016562542525606630160374691593895118", - /* k=5 r=32 */ - "36581797046584068049060372878520385032448812009597153775348195406694427778894", - /* k=6 r=64 */ - "31519469946562159605140591558550197856588417350474800936898404023113662197331", // iki cia pakeista - /* k=7 r=128 */ - "3535074550574477753284711575859241084625659976293648650204577841347885064712", - /* k=8 r=256 */ - "21071158244812412064791010377580296085971058123779034548857891862303448703672", - /* k=9 r=512 */ - "12531186154666751577774347439625638674013361494693625348921624593362229945844", - /* k=10 r=1024 */ - "21328829733576761151404230261968752855781179864716879432436835449516750606329", - /* k=11 r=2048 */ - "30450688096165933124094588052280452792793350252342406284806180166247113753719", - /* k=12 r=4096 */ - "7712148129911606624315688729500842900222944762233088101895611600385646063109", - /* k=13 r=8192 */ - "4862464726302065505506688039068558711848980475932963135959468859464391638674", - /* k=14 r=16384 */ - "36362449573598723777784795308133589731870287401357111047147227126550012376068", - /* k=15 r=32768 */ - "30195699792882346185164345110260439085017223719129789169349923251189180189908", - /* k=16 r=65536 */ - "46605497109352149548364111935960392432509601054990529243781317021485154656122", - /* k=17 r=131072 */ - "2655041105015028463885489289298747241391034429256407017976816639065944350782", - /* k=18 r=262144 */ - "42951892408294048319804799042074961265671975460177021439280319919049700054024", - /* k=19 r=524288 */ - "26418991338149459552592774439099778547711964145195139895155358980955972635668", - /* k=20 r=1048576 */ - "23615957371642610195417524132420957372617874794160903688435201581369949179370", - /* k=21 r=2097152 */ - "50175287592170768174834711592572954584642344504509533259061679462536255873767", - /* k=22 r=4194304 */ - "1664636601308506509114953536181560970565082534259883289958489163769791010513", - /* k=23 r=8388608 */ - "36760611456605667464829527713580332378026420759024973496498144810075444759800", - /* k=24 r=16777216 */ - "13205172441828670567663721566567600707419662718089030114959677511969243860524", - /* k=25 r=33554432 */ - "10335750295308996628517187959952958185340736185617535179904464397821611796715", - /* k=26 r=67108864 */ - "51191008403851428225654722580004101559877486754971092640244441973868858562750", - /* k=27 r=134217728 */ - "24000695595003793337811426892222725080715952703482855734008731462871475089715", - /* k=28 r=268435456 */ - "18727201054581607001749469507512963489976863652151448843860599973148080906836", - /* k=29 r=536870912 */ - "50819341139666003587274541409207395600071402220052213520254526953892511091577", - /* k=30 r=1073741824 */ - "3811138593988695298394477416060533432572377403639180677141944665584601642504", - /* k=31 r=2147483648 */ - "43599901455287962219281063402626541872197057165786841304067502694013639882090", -]; - -pub const G1_GENERATOR: G1 = G1 { - x: Fp { - d: [ - 0x5cb38790fd530c16, - 0x7817fc679976fff5, - 0x154f95c7143ba1c1, - 0xf0ae6acdf3d0e747, - 0xedce6ecc21dbf440, - 0x120177419e0bfb75, - ], - }, - y: Fp { - d: [ - 0xbaac93d50ce72271, - 0x8c22631a7918fd8e, - 0xdd595f13570725ce, - 0x51ac582950405194, - 0x0e1c8c3fad0059c0, - 0x0bbc3efc5008a26a, - ], - }, - z: Fp { - d: [ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, - ], - }, -}; - -pub const G1_NEGATIVE_GENERATOR: G1 = G1 { - x: Fp { - d: [ - 0x5cb38790fd530c16, - 0x7817fc679976fff5, - 0x154f95c7143ba1c1, - 0xf0ae6acdf3d0e747, - 0xedce6ecc21dbf440, - 0x120177419e0bfb75, - ], - }, - y: Fp { - d: [ - 0xff526c2af318883a, - 0x92899ce4383b0270, - 0x89d7738d9fa9d055, - 0x12caf35ba344c12a, - 0x3cff1b76964b5317, - 0x0e44d2ede9774430, - ], - }, - z: Fp { - d: [ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, - ], - }, -}; - -pub static mut SCALE_2_ROOT_OF_UNITY: Vec = vec![]; -pub static mut GLOBALS_INITIALIZED: bool = false; -pub static mut DEFAULT_GLOBALS_INITIALIZED: bool = false; -pub const PRIMITIVE_ROOT: i32 = 5; - -pub fn make_data(n: usize) -> Vec { - // Multiples of g1_gen - if n == 0 { - return vec![]; - } - let mut data: Vec = vec![G1_GENERATOR]; - for _ in 1..n { - let g1 = data.last().unwrap() + &G1_GENERATOR.clone(); - data.push(g1); - } - data -} - -/// # Safety -/// -/// use of mutable static is unsafe and requires unsafe function or block -pub unsafe fn init_globals() { - if GLOBALS_INITIALIZED && DEFAULT_GLOBALS_INITIALIZED { - return; - } - SCALE_2_ROOT_OF_UNITY = SCALE_2_ROOT_OF_UNITY_PR5_STRINGS - .iter() - .map(|x| Fr::from_str(x, 10).unwrap()) - .collect(); - - GLOBALS_INITIALIZED = true; - DEFAULT_GLOBALS_INITIALIZED = true; -} - -/// # Safety -/// -/// use of mutable static is unsafe and requires unsafe function or block -pub unsafe fn init_globals_custom(root_strings: [&str; 32]) { - SCALE_2_ROOT_OF_UNITY = root_strings - .iter() - .map(|x| Fr::from_str(x, 10).unwrap()) - .collect(); - - GLOBALS_INITIALIZED = true; - DEFAULT_GLOBALS_INITIALIZED = false; -} - -pub fn expand_root_of_unity(root: &Fr) -> Vec { - let mut root_z = vec![Fr::one(), *root]; - let mut i = 1; - while !root_z[i].is_one() { - let next = &root_z[i] * root; - root_z.push(next); - i += 1; - } - root_z -} - -#[derive(Debug, Clone)] -pub struct FFTSettings { - pub max_width: usize, - pub root_of_unity: Fr, - pub expanded_roots_of_unity: Vec, - pub reverse_roots_of_unity: Vec, - pub roots_of_unity: Vec, -} - -impl Default for FFTSettings { - fn default() -> Self { - Self::new(0) - } -} - -impl FFTSettings { - //fix this mess - /// # Safety - /// - /// use of mutable static is unsafe and requires unsafe function or block - pub fn new(max_scale: u8) -> FFTSettings { - let root_of_unity: Fr; - unsafe { - init_globals(); - root_of_unity = SCALE_2_ROOT_OF_UNITY[max_scale as usize] - } - let expanded_roots_of_unity = expand_root_of_unity(&root_of_unity); - let mut reverse_roots_of_unity = expanded_roots_of_unity.clone(); - reverse_roots_of_unity.reverse(); - - // Permute the roots of unity - let mut roots_of_unity = expanded_roots_of_unity.clone(); - reverse_bit_order(&mut roots_of_unity); - - FFTSettings { - max_width: 1 << max_scale, - root_of_unity, - expanded_roots_of_unity, - reverse_roots_of_unity, - roots_of_unity, - } - } - - /// # Safety - /// - /// use of mutable static is unsafe and requires unsafe function or block - pub fn new_custom_primitive_roots( - max_scale: u8, - root_strings: [&str; 32], - ) -> Result { - let root_of_unity: Fr; - unsafe { - init_globals_custom(root_strings); - if max_scale as usize >= SCALE_2_ROOT_OF_UNITY.len() { - return Err(String::from( - "Scale is expected to be within root of unity matrix row size", - )); - } - root_of_unity = SCALE_2_ROOT_OF_UNITY[max_scale as usize] - } - - let expanded_roots_of_unity = expand_root_of_unity(&root_of_unity); - let mut reverse_roots_of_unity = expanded_roots_of_unity.clone(); - reverse_roots_of_unity.reverse(); - - // Permute the roots of unity - let mut roots_of_unity = expanded_roots_of_unity.clone(); - reverse_bit_order(&mut roots_of_unity)?; - - Ok(FFTSettings { - max_width: 1 << max_scale, - root_of_unity, - expanded_roots_of_unity, - reverse_roots_of_unity, - roots_of_unity, - }) - } - - // #[cfg(feature = "parallel")] - fn _fft( - values: &[Fr], - offset: usize, - stride: usize, - roots_of_unity: &[Fr], - root_stride: usize, - out: &mut [Fr], - ) { - // check if correct value is checked in case of a bug! - if out.len() <= 4 { - // if the value count is small, run the unoptimized version instead. // TODO tune threshold. - return FFTSettings::_simple_ftt( - values, - offset, - stride, - roots_of_unity, - root_stride, - out, - ); - } - - let half = out.len() >> 1; - - #[cfg(feature = "parallel")] - { - if half > 256 { - let (lo, hi) = out.split_at_mut(half); - rayon::join( - || { - FFTSettings::_fft( - values, - offset, - stride << 1, - roots_of_unity, - root_stride << 1, - lo, - ) - }, - || { - FFTSettings::_fft( - values, - offset + stride, - stride << 1, - roots_of_unity, - root_stride << 1, - hi, - ) - }, - ); - } else { - FFTSettings::_fft( - values, - offset, - stride << 1, - roots_of_unity, - root_stride << 1, - &mut out[..half], - ); - FFTSettings::_fft( - values, - offset + stride, - stride << 1, - roots_of_unity, - root_stride << 1, - &mut out[half..], - ); - } - } - #[cfg(not(feature = "parallel"))] - { - // left - FFTSettings::_fft( - values, - offset, - stride << 1, - roots_of_unity, - root_stride << 1, - &mut out[..half], - ); - // right - FFTSettings::_fft( - values, - offset + stride, - stride << 1, - roots_of_unity, - root_stride << 1, - &mut out[half..], - ); - } - - for i in 0..half { - let root = &roots_of_unity[i * root_stride]; - let y_times_root = &out[i + half] * root; - out[i + half] = out[i] - y_times_root; - out[i] = out[i] + y_times_root; - } - } - - fn _simple_ftt( - values: &[Fr], - offset: usize, - stride: usize, - roots_of_unity: &[Fr], - root_stride: usize, - out: &mut [Fr], - ) { - let out_len = out.len(); - let init_last = values[offset] * roots_of_unity[0]; - - for i in 0..out_len { - let mut last = init_last; - for j in 1..out_len { - let jv = &values[offset + j * stride]; - let r = &roots_of_unity[((i * j) % out_len) * root_stride]; - // last += (jv * r) - last = last + (jv * r); - } - out[i] = last; - } - } - - pub fn inplace_fft(&self, values: &[Fr], inv: bool) -> Vec { - if inv { - let root_z: Vec = self - .reverse_roots_of_unity - .iter() - .copied() - .take(self.max_width) - .collect(); - let stride = self.max_width / values.len(); - - let mut out = vec![Fr::default(); values.len()]; - FFTSettings::_fft(values, 0, 1, &root_z, stride, &mut out); - - let inv_len = Fr::from_int(values.len() as i32).get_inv(); - for item in out.iter_mut() { - *item = *item * inv_len; - } - out - } else { - let root_z: Vec = self - .expanded_roots_of_unity - .iter() - .copied() - .take(self.max_width) - .collect(); - let stride = self.max_width / values.len(); - - let mut out = vec![Fr::default(); values.len()]; - FFTSettings::_fft(values, 0, 1, &root_z, stride, &mut out); - - out - } - } - - pub fn fft(&self, values: &[Fr], inv: bool) -> Result, String> { - if values.len() > self.max_width { - return Err(String::from( - "Supplied values is longer than the available max width", - )); - } - let n = next_pow_of_2(values.len()); - - let diff = n - values.len(); - let tail = iter::repeat(Fr::zero()).take(diff); - let values_copy: Vec = values.iter().copied().chain(tail).collect(); - - Ok(self.inplace_fft(&values_copy, inv)) - } - - pub fn fft_fr_slow( - result: &mut [Fr], - values: &[Fr], - stride: usize, - passed_roots_of_unity: &[Fr], - root_stride: usize, - ) { - FFTSettings::_simple_ftt( - values, - 0, - stride, - passed_roots_of_unity, - root_stride, - result, - ); - } - - pub fn fft_fr_fast( - result: &mut [Fr], - values: &[Fr], - stride: usize, - passed_roots_of_unity: &[Fr], - root_stride: usize, - ) { - FFTSettings::_fft( - values, - 0, - stride, - passed_roots_of_unity, - root_stride, - result, - ); - } - - pub fn fft_g1(&self, values: &[G1]) -> Result, String> { - if values.len() > self.max_width { - return Err(String::from( - "length of values is longer than the available max width", - )); - } - if !is_power_of_2(values.len()) { - return Err(String::from("length of values must be a power of two")); - } - // TODO: check if copy can be removed, opt? - // let vals_copy = values.clone(); - - let root_z: Vec = self - .expanded_roots_of_unity - .iter() - .take(self.max_width) - .copied() - .collect(); - - let stride = self.max_width / values.len(); - let mut out = vec![G1::zero(); values.len()]; - - FFTSettings::_fft_g1(values, 0, 1, &root_z, stride, &mut out); - - Ok(out) - } - - //just copied of for fk20_matrix - pub fn fft_g1_inv(&self, values: &[G1]) -> Result, String> { - if values.len() > self.max_width { - return Err(String::from( - "length of values is longer than the available max width", - )); - } - if !is_power_of_2(values.len()) { - return Err(String::from("length of values must be a power of two")); - } - // TODO: check if copy can be removed, opt? - // let vals_copy = values.clone(); - - let root_z: Vec = self - .reverse_roots_of_unity - .iter() - .take(self.max_width) - .copied() - .collect(); - - let stride = self.max_width / values.len(); - let mut out = vec![G1::zero(); values.len()]; - - FFTSettings::_fft_g1(values, 0, 1, &root_z, stride, &mut out); - - let inv_len = Fr::from_int(values.len() as i32).get_inv(); - for item in out.iter_mut() { - // for i in 0..out.len() { - *item = &*item * &inv_len; - } - - Ok(out) - } - - // #[cfg(feature = "parallel")] - fn _fft_g1( - values: &[G1], - value_offset: usize, - value_stride: usize, - roots_of_unity: &[Fr], - roots_stride: usize, - out: &mut [G1], - ) { - //TODO: fine tune for opt, maybe resolve number dinamically based on experiments - if out.len() <= 4 { - return FFTSettings::_fft_g1_simple( - values, - value_offset, - value_stride, - roots_of_unity, - roots_stride, - out, - ); - } - - let half = out.len() >> 1; - - #[cfg(feature = "parallel")] - { - let (lo, hi) = out.split_at_mut(half); - rayon::join( - || { - FFTSettings::_fft_g1( - values, - value_offset, - value_stride << 1, - roots_of_unity, - roots_stride << 1, - lo, - ) - }, - || { - FFTSettings::_fft_g1( - values, - value_offset + value_stride, - value_stride << 1, - roots_of_unity, - roots_stride << 1, - hi, - ) - }, - ); - } - #[cfg(not(feature = "parallel"))] - { - // left - FFTSettings::_fft_g1( - values, - value_offset, - value_stride << 1, - roots_of_unity, - roots_stride << 1, - &mut out[..half], - ); - // right - FFTSettings::_fft_g1( - values, - value_offset + value_stride, - value_stride << 1, - roots_of_unity, - roots_stride << 1, - &mut out[half..], - ); - } - - for i in 0..half { - let x = out[i]; - let y = out[i + half]; - let root = &roots_of_unity[i * roots_stride]; - - let y_times_root = y * root; - G1::add(&mut out[i], &x, &y_times_root); - out[i + half] = x - y_times_root; - } - } - - fn _fft_g1_simple( - values: &[G1], - value_offset: usize, - value_stride: usize, - roots_of_unity: &[Fr], - roots_stride: usize, - out: &mut [G1], - ) { - let l = out.len(); - for i in 0..l { - // TODO: check this logic with a working brain, there could be a simpler way to write this; - let mut v = &values[value_offset] * &roots_of_unity[0]; - let mut last = v; - for j in 1..l { - v = &values[value_offset + j * value_stride] - * &roots_of_unity[((i * j) % l) * roots_stride]; - let temp = last; - last = &temp + &v; - } - out[i] = last; - } - } - - pub fn fft_g1_slow( - out: &mut [G1], - values: &[G1], - stride: usize, - passed_roots_of_unity: &[Fr], - root_stride: usize, - _n: usize, - ) { - FFTSettings::_fft_g1_simple(values, 0, stride, passed_roots_of_unity, root_stride, out); - } - - pub fn fft_g1_fast( - out: &mut [G1], - values: &[G1], - stride: usize, - passed_roots_of_unity: &[Fr], - root_stride: usize, - _n: usize, - ) { - FFTSettings::_fft_g1(values, 0, stride, passed_roots_of_unity, root_stride, out); - } -} diff --git a/mcl/kzg/src/fk20_matrix.rs b/mcl/kzg/src/fk20_matrix.rs deleted file mode 100644 index b1f9a6501..000000000 --- a/mcl/kzg/src/fk20_matrix.rs +++ /dev/null @@ -1,346 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::data_types::g1::G1; -use crate::fk20_fft::*; -use crate::kzg10::*; -use crate::kzg_settings::KZGSettings; -use std::iter; - -use kzg::common_utils::is_power_of_2; -use kzg::common_utils::reverse_bit_order; -#[cfg(feature = "parallel")] -use rayon::prelude::*; - -impl FFTSettings { - pub fn toeplitz_part_1(&self, x: &[G1]) -> Result, String> { - let n = x.len(); - - // extend x with zeroes - let tail = vec![G1::zero(); n]; - let x_ext: Vec = x.iter().cloned().chain(tail).collect(); - - self.fft_g1(&x_ext) - } - - pub fn toeplitz_part_2(&self, coeffs: &[Fr], x_ext_fft: &[G1]) -> Result, String> { - let toeplitz_coeffs_fft = self.fft(coeffs, false).unwrap(); - - #[cfg(feature = "parallel")] - { - let ret: Vec<_> = (0..coeffs.len()) - .into_par_iter() - .map(|i| x_ext_fft[i] * &toeplitz_coeffs_fft[i]) - .collect(); - Ok(ret) - } - - #[cfg(not(feature = "parallel"))] - { - let mut ret = Vec::new(); - for i in 0..coeffs.len() { - ret.push(x_ext_fft[i] * &toeplitz_coeffs_fft[i]); - } - Ok(ret) - } - } - - pub fn toeplitz_part_3(&self, h_ext_fft: &[G1]) -> Result, String> { - let n2 = h_ext_fft.len(); - let n = n2 / 2; - - let mut ret = self.fft_g1_inv(h_ext_fft).unwrap(); - - for item in ret.iter_mut().take(n2).skip(n) { - *item = G1::G1_IDENTITY; - } - - Ok(ret) - } -} - -#[derive(Debug, Clone, Default)] -pub struct FK20SingleMatrix { - pub x_ext_fft: Vec, - pub kzg_settings: KZGSettings, -} - -impl FK20SingleMatrix { - pub fn new(kzg_settings: &KZGSettings, n2: usize) -> Result { - let n = n2 >> 1; // div by 2 - - if !is_power_of_2(n2) { - return Err(String::from("n2 must be a power of two")); - } - if n2 < 2 { - return Err(String::from("n2 must be greater than or equal to 2")); - } - if n2 > kzg_settings.fft_settings.max_width { - return Err(String::from( - "n2 must be less than or equal to fft settings max width", - )); - } - - let mut x = Vec::new(); - for i in 0..n - 1 { - x.push(kzg_settings.curve.g1_points[n - 2 - i]); - } - x.push(G1::G1_IDENTITY); - - let x_ext_fft = kzg_settings.fft_settings.toeplitz_part_1(&x).unwrap(); - let kzg_settings = kzg_settings.clone(); - - Ok(Self { - kzg_settings, - x_ext_fft, - }) - } - - pub fn dau_using_fk20_single(&self, polynomial: &Polynomial) -> Result, String> { - let n = polynomial.order(); - let n2 = n << 1; - - if !is_power_of_2(n2) { - return Err(String::from("n2 must be a power of two")); - } - if n2 > self.kzg_settings.fft_settings.max_width { - return Err(String::from( - "n2 must be less than or equal to fft settings max width", - )); - } - - let mut proofs = self.fk20_single_dao_optimized(polynomial).unwrap(); - reverse_bit_order(&mut proofs)?; - - Ok(proofs) - } - - pub fn fk20_single_dao_optimized(&self, polynomial: &Polynomial) -> Result, String> { - let n = polynomial.order(); - let n2 = n * 2; - - if !is_power_of_2(n2) { - return Err(String::from("n2 must be a power of two")); - } - if n2 > self.kzg_settings.fft_settings.max_width { - return Err(String::from( - "n2 must be less than or equal to fft settings max width", - )); - } - - let toeplitz_coeffs = polynomial.toeplitz_coeffs_step_strided(0, 1); - let h_ext_fft = self - .kzg_settings - .fft_settings - .toeplitz_part_2(&toeplitz_coeffs, &self.x_ext_fft) - .unwrap(); - let h = self - .kzg_settings - .fft_settings - .toeplitz_part_3(&h_ext_fft) - .unwrap(); - - self.kzg_settings.fft_settings.fft_g1(&h) - } -} - -#[derive(Debug, Clone)] -pub struct FK20Matrix { - pub x_ext_fft_files: Vec>, - pub chunk_len: usize, - pub kzg_settings: KZGSettings, -} - -impl Default for FK20Matrix { - fn default() -> Self { - Self { - kzg_settings: KZGSettings::default(), - chunk_len: 1, - x_ext_fft_files: vec![], - } - } -} - -impl FK20Matrix { - pub fn new(kzg_settings: &KZGSettings, n2: usize, chunk_len: usize) -> Result { - let n = n2 >> 1; // div by 2 - let k = n / chunk_len; - - if !is_power_of_2(n2) { - return Err(String::from("n2 must be a power of two")); - } - if !is_power_of_2(chunk_len) { - return Err(String::from("chunk_len must be a power of two")); - } - if n2 < 2 { - return Err(String::from("n2 must be greater than or equal to 2")); - } - if n2 > kzg_settings.fft_settings.max_width { - return Err(String::from( - "n2 must be less than or equal to kzg settings max width", - )); - } - if n2 > kzg_settings.fft_settings.max_width { - return Err(String::from( - "n2 must be less than or equal to fft settings max width", - )); - } - if chunk_len > n2 / 2 { - return Err(String::from("chunk_len must be greater or equal to n2 / 2")); - } - - let mut x_ext_fft_files: Vec> = vec![vec![]; chunk_len]; - for (i, item) in x_ext_fft_files.iter_mut().enumerate().take(chunk_len) { - *item = FK20Matrix::x_ext_fft_precompute( - &kzg_settings.fft_settings, - &kzg_settings.curve, - n, - k, - chunk_len, - i, - ) - .unwrap(); - } - - Ok(FK20Matrix { - x_ext_fft_files, - chunk_len, - kzg_settings: kzg_settings.clone(), - }) - } - - #[allow(clippy::many_single_char_names)] - fn x_ext_fft_precompute( - fft_settings: &FFTSettings, - curve: &Curve, - n: usize, - k: usize, - chunk_len: usize, - offset: usize, - ) -> Result, String> { - let mut x: Vec = vec![G1::default(); k]; - - let mut start = 0; - let temp = chunk_len + 1 + offset; - if n >= temp { - start = n - temp; - } - - let mut i = 0; - let mut j = start + chunk_len; - - while i + 1 < k { - // hack to remove overflow checking, - // could just move this to the bottom and define j as start, but then need to check for overflows - // basically last j -= chunk_len overflows, but it's not used to access the array, as the i + 1 < k is false - j -= chunk_len; - x[i] = curve.g1_points[j]; - i += 1; - } - - x[k - 1] = G1::zero(); - - fft_settings.toeplitz_part_1(&x) - } - - pub fn dau_using_fk20_multi(&self, polynomial: &Polynomial) -> Result, String> { - let n = polynomial.order(); - let n2 = n << 1; - - if !is_power_of_2(n2) { - return Err(String::from("n2 must be a power of two")); - } - if n2 > self.kzg_settings.fft_settings.max_width { - return Err(String::from( - "n2 must be less than or equal to fft settings max width", - )); - } - - let extended_poly = polynomial.get_extended(n2); - let mut proofs = self.fk20_multi_dao_optimized(&extended_poly).unwrap(); - reverse_bit_order(&mut proofs)?; - - Ok(proofs) - } - - pub fn fk20_multi_dao_optimized(&self, polynomial: &Polynomial) -> Result, String> { - let n = polynomial.order() >> 1; - let k = n / self.chunk_len; - let k2 = k << 1; - - let n2 = n << 1; - if !is_power_of_2(n2) { - return Err(String::from("n2 must be a power of two")); - } - if n2 > self.kzg_settings.fft_settings.max_width { - return Err(String::from( - "n2 must be less than or equal to fft settings max width", - )); - } - - let mut h_ext_fft = vec![G1::zero(); k2]; - // TODO: this operates on an extended poly, but doesn't use the extended values? - // literally just using the poly without the zero trailing tail, makes more sense to take it in as a param, or use without the tail; - let reduced_poly = Polynomial::from_fr(polynomial.coeffs.iter().copied().take(n).collect()); - - for i in 0..self.chunk_len { - let toeplitz_coeffs = reduced_poly.toeplitz_coeffs_step_strided(i, self.chunk_len); - let h_ext_fft_file = self - .kzg_settings - .fft_settings - .toeplitz_part_2(&toeplitz_coeffs, &self.x_ext_fft_files[i]) - .unwrap(); - - for j in 0..k2 { - let tmp = &h_ext_fft[j] + &h_ext_fft_file[j]; - h_ext_fft[j] = tmp; - } - } - - let tail = iter::repeat(G1::zero()).take(k); - let h: Vec = self - .kzg_settings - .fft_settings - .toeplitz_part_3(&h_ext_fft) - .unwrap() - .into_iter() - .take(k) - .chain(tail) - .collect(); - - self.kzg_settings.fft_settings.fft_g1(&h) - } -} - -impl Polynomial { - pub fn extend(vec: &[Fr], size: usize) -> Vec { - if size < vec.len() { - return vec.to_owned(); - } - let to_pad = size - vec.len(); - let tail = iter::repeat(Fr::zero()).take(to_pad); - let result: Vec = vec.iter().copied().chain(tail).collect(); - - result - } - - pub fn get_extended(&self, size: usize) -> Polynomial { - Polynomial::from_fr(Polynomial::extend(&self.coeffs, size)) - } - - fn toeplitz_coeffs_step_strided(&self, offset: usize, stride: usize) -> Vec { - let n = self.order(); - let k = n / stride; - let k2 = k << 1; - - // [last] + [0]*(n+1) + [1 .. n-2] - let mut toeplitz_coeffs = vec![Fr::zero(); k2]; - toeplitz_coeffs[0] = self.coeffs[n - 1 - offset]; - - let mut j = (stride << 1) - offset - 1; - for item in toeplitz_coeffs.iter_mut().take(k2).skip(k + 2) { - *item = self.coeffs[j]; - j += stride; - } - - toeplitz_coeffs - } -} diff --git a/mcl/kzg/src/init_def.rs b/mcl/kzg/src/init_def.rs deleted file mode 100644 index b04f628bd..000000000 --- a/mcl/kzg/src/init_def.rs +++ /dev/null @@ -1,276 +0,0 @@ -macro_rules! common_impl { - ($t:ty, $is_equal_fn:ident, $is_zero_fn:ident) => { - impl PartialEq for $t { - fn eq(&self, rhs: &Self) -> bool { - unsafe { $is_equal_fn(self, rhs) == 1 } - } - } - impl $t { - pub fn zero() -> $t { - Default::default() - } - pub fn clear(&mut self) { - *self = <$t>::zero() - } - pub fn is_zero(&self) -> bool { - unsafe { $is_zero_fn(self) == 1 } - } - } - }; -} -macro_rules! is_valid_impl { - ($t:ty, $is_valid_fn:ident) => { - impl $t { - /// # Safety - /// - /// MCL Function, unsure why it is unsafe - pub fn is_valid(&self) -> bool { - unsafe { $is_valid_fn(self) == 1 } - } - } - }; -} - -macro_rules! serialize_impl { - ($t:ty, $size:expr, $serialize_fn:ident, $deserialize_fn:ident) => { - impl $t { - /// # Safety - /// - /// MCL Function, unsure why it is unsafe - pub fn deserialize(&mut self, buf: &[u8]) -> bool { - unsafe { $deserialize_fn(self, buf.as_ptr(), buf.len()) > 0 } - } - /// # Safety - /// - /// MCL Function, unsure why it is unsafe - pub fn serialize(&self) -> Vec { - let size = unsafe { $size } as usize; - let mut buf: Vec = Vec::with_capacity(size); - let n: usize; - unsafe { - n = $serialize_fn(buf.as_mut_ptr(), size, self); - } - if n == 0 { - panic!("serialize"); - } - unsafe { - buf.set_len(n); - } - buf - } - } - }; -} - -macro_rules! str_impl { - ($t:ty, $maxBufSize:expr, $get_str_fn:ident, $set_str_fn:ident) => { - impl $t { - pub fn from_str(s: &str, base: i32) -> Option<$t> { - let mut v = <$t>::zero(); - if v.set_str(s, base) { - return Some(v); - } - None - } - pub fn set_str(&mut self, s: &str, base: i32) -> bool { - unsafe { $set_str_fn(self, s.as_ptr(), s.len(), base) == 0 } - } - pub fn get_str(&self, io_mode: i32) -> String { - let mut buf: [u8; $maxBufSize] = [0; $maxBufSize]; - let n: usize; - unsafe { - n = $get_str_fn(buf.as_mut_ptr(), buf.len(), self, io_mode); - } - if n == 0 { - panic!("mclBnFr_getStr"); - } - unsafe { std::str::from_utf8_unchecked(&buf[0..n]).into() } - } - } - }; -} - -macro_rules! int_impl { - ($t:ty, $set_int_fn:ident, $is_one_fn:ident) => { - impl $t { - pub fn from_int(x: i32) -> $t { - let mut v = <$t>::zero(); - v.set_int(x); - v - } - pub fn set_int(&mut self, x: i32) { - unsafe { - $set_int_fn(self, x); - } - } - pub fn is_one(&self) -> bool { - unsafe { $is_one_fn(self) == 1 } - } - } - }; -} - -macro_rules! base_field_impl { - ($t:ty, $set_little_endian_fn:ident, $get_little_endian_fn:ident, $set_little_endian_mod_fn:ident, $set_hash_of_fn:ident, $set_by_csprng_fn:ident, $is_odd_fn:ident, $is_negative_fn:ident, $square_root_fn:ident) => { - impl $t { - pub fn set_little_endian(&mut self, buf: &[u8]) -> bool { - unsafe { $set_little_endian_fn(self, buf.as_ptr(), buf.len()) == 0 } - } - pub fn get_little_endian(&self, buf: &mut [u8]) -> bool { - unsafe { $get_little_endian_fn(buf.as_mut_ptr(), buf.len(), self) > 0 } - } - pub fn set_little_endian_mod(&mut self, buf: &[u8]) -> bool { - unsafe { $set_little_endian_mod_fn(self, buf.as_ptr(), buf.len()) == 0 } - } - pub fn set_hash_of(&mut self, buf: &[u8]) -> bool { - unsafe { $set_hash_of_fn(self, buf.as_ptr(), buf.len()) == 0 } - } - pub fn set_by_csprng(&mut self) { - unsafe { $set_by_csprng_fn(self) } - } - pub fn is_odd(&self) -> bool { - unsafe { $is_odd_fn(self) == 1 } - } - pub fn is_negative(&self) -> bool { - unsafe { $is_negative_fn(self) == 1 } - } - pub fn square_root(y: &mut $t, x: &$t) -> bool { - unsafe { $square_root_fn(y, x) == 0 } - } - } - }; -} - -macro_rules! add_op_impl { - ($t:ty, $add_fn:ident, $sub_fn:ident, $neg_fn:ident) => { - impl $t { - pub fn add(z: &mut $t, x: &$t, y: &$t) { - unsafe { $add_fn(z, x, y) } - } - pub fn sub(z: &mut $t, x: &$t, y: &$t) { - unsafe { $sub_fn(z, x, y) } - } - pub fn neg(y: &mut $t, x: &$t) { - unsafe { $neg_fn(y, x) } - } - } - impl<'a> Add for &'a $t { - type Output = $t; - fn add(self, other: &$t) -> $t { - let mut v = <$t>::zero(); - <$t>::add(&mut v, &self, &other); - v - } - } - impl<'a> AddAssign<&'a $t> for $t { - fn add_assign(&mut self, other: &$t) { - // how can I write this? - // unsafe { <$t>::add(&mut self, &self, &other); } - let mut v = <$t>::zero(); - <$t>::add(&mut v, &self, &other); - *self = v; - } - } - impl<'a> Sub for &'a $t { - type Output = $t; - fn sub(self, other: &$t) -> $t { - let mut v = <$t>::zero(); - <$t>::sub(&mut v, &self, &other); - v - } - } - impl<'a> SubAssign<&'a $t> for $t { - fn sub_assign(&mut self, other: &$t) { - let mut v = <$t>::zero(); - <$t>::sub(&mut v, &self, &other); - *self = v; - } - } - }; -} - -macro_rules! field_mul_op_impl { - ($t:ty, $mul_fn:ident, $div_fn:ident, $inv_fn:ident, $sqr_fn:ident) => { - impl $t { - pub fn mul(z: &mut $t, x: &$t, y: &$t) { - unsafe { $mul_fn(z, x, y) } - } - pub fn div(z: &mut $t, x: &$t, y: &$t) { - if <$t>::is_zero(y) { - *z = <$t>::zero(); - } else { - unsafe { $div_fn(z, x, y) } - } - } - pub fn inv(y: &mut $t, x: &$t) { - unsafe { $inv_fn(y, x) } - } - pub fn sqr(y: &mut $t, x: &$t) { - unsafe { $sqr_fn(y, x) } - } - } - impl<'a> Mul for &'a $t { - type Output = $t; - fn mul(self, other: &$t) -> $t { - let mut v = <$t>::zero(); - <$t>::mul(&mut v, &self, &other); - v - } - } - impl<'a> MulAssign<&'a $t> for $t { - fn mul_assign(&mut self, other: &$t) { - let mut v = <$t>::zero(); - <$t>::mul(&mut v, &self, &other); - *self = v; - } - } - impl<'a> Div for &'a $t { - type Output = $t; - fn div(self, other: &$t) -> $t { - let mut v = <$t>::zero(); - <$t>::div(&mut v, &self, &other); - v - } - } - impl<'a> DivAssign<&'a $t> for $t { - fn div_assign(&mut self, other: &$t) { - let mut v = <$t>::zero(); - <$t>::div(&mut v, &self, &other); - *self = v; - } - } - }; -} - -macro_rules! ec_impl { - ($t:ty, $dbl_fn:ident, $mul_fn:ident, $normalize_fn:ident, $set_hash_and_map_fn:ident) => { - impl $t { - pub fn dbl(y: &mut $t, x: &$t) { - unsafe { $dbl_fn(y, x) } - } - pub fn mul(z: &mut $t, x: &$t, y: &Fr) { - unsafe { $mul_fn(z, x, y) } - } - pub fn normalize(y: &mut $t, x: &$t) { - unsafe { $normalize_fn(y, x) } - } - pub fn set_hash_of(&mut self, buf: &[u8]) -> bool { - unsafe { $set_hash_and_map_fn(self, buf.as_ptr(), buf.len()) == 0 } - } - } - }; -} - -macro_rules! get_str_impl { - ($get_str_fn:ident) => {{ - let mut buf: [u8; 256] = [0; 256]; - let n: usize; - unsafe { - n = $get_str_fn(buf.as_mut_ptr(), buf.len()); - } - if n == 0 { - panic!("get_str"); - } - unsafe { std::str::from_utf8_unchecked(&buf[0..n]).into() } - }}; -} diff --git a/mcl/kzg/src/kzg10.rs b/mcl/kzg/src/kzg10.rs deleted file mode 100644 index 0ded01a51..000000000 --- a/mcl/kzg/src/kzg10.rs +++ /dev/null @@ -1,684 +0,0 @@ -use crate::data_types::{fr::*, g1::*, g2::*, gt::*}; -use crate::fk20_fft::{FFTSettings, G1_GENERATOR}; -use crate::mcl_methods::{final_exp, mclBn_FrEvaluatePolynomial, pairing}; -use kzg::common_utils::{log_2, next_pow_of_2}; -use std::{cmp::min, iter, ops}; - -#[cfg(feature = "parallel")] -use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; - -const G1_GEN_X: &str = "3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507"; -const G1_GEN_Y: &str = "1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569"; -const G2_GEN_X_D0: &str = "352701069587466618187139116011060144890029952792775240219908644239793785735715026873347600343865175952761926303160"; -const G2_GEN_X_D1: &str = "3059144344244213709971259814753781636986470325476647558659373206291635324768958432433509563104347017837885763365758"; -const G2_GEN_Y_D0: &str = "1985150602287291935568054521177171638300868978215655730859378665066344726373823718423869104263333984641494340347905"; -const G2_GEN_Y_D1: &str = "927553665492332455747201965776037880757740193453592970025027978793976877002675564980949289727957565575433344219582"; - -impl G1 { - pub fn gen() -> G1 { - let mut g1 = G1::default(); - g1.x.set_str(G1_GEN_X, 10); - g1.y.set_str(G1_GEN_Y, 10); - g1.z.set_int(1); - g1 - } - - pub fn pair(&self, rhs: &G2) -> GT { - let mut gt = GT::default(); - - pairing(&mut gt, self, rhs); - - gt - } - - pub fn random() -> G1 { - let fr = Fr::random(); - &G1_GENERATOR * &fr - } -} - -impl ops::Mul<&Fr> for G1 { - type Output = G1; - fn mul(self, rhs: &Fr) -> Self::Output { - let mut g1 = G1::default(); - G1::mul(&mut g1, &self, rhs); - - g1 - } -} - -impl ops::Mul<&Fr> for &G1 { - type Output = G1; - fn mul(self, rhs: &Fr) -> Self::Output { - let mut g1 = G1::default(); - G1::mul(&mut g1, self, rhs); - - g1 - } -} - -impl ops::Mul<&Fr> for &mut G1 { - type Output = G1; - fn mul(self, rhs: &Fr) -> Self::Output { - let mut g1 = G1::default(); - G1::mul(&mut g1, self, rhs); - - g1 - } -} - -impl ops::Sub for G1 { - type Output = G1; - fn sub(self, rhs: G1) -> Self::Output { - let mut g1 = G1::default(); - G1::sub(&mut g1, &self, &rhs); - - g1 - } -} - -impl GT { - pub fn get_final_exp(&self) -> GT { - let mut gt = GT::default(); - final_exp(&mut gt, self); - - gt - } - - pub fn get_inv(&self) -> GT { - let mut gt = GT::default(); - GT::inv(&mut gt, self); - - gt - } -} - -impl ops::Mul for GT { - type Output = GT; - fn mul(self, rhs: GT) -> Self::Output { - let mut gt = GT::default(); - GT::mul(&mut gt, &self, &rhs); - - gt - } -} - -impl G2 { - pub fn gen() -> G2 { - let mut g2 = G2::default(); - g2.x.d[0].set_str(G2_GEN_X_D0, 10); - g2.x.d[1].set_str(G2_GEN_X_D1, 10); - g2.y.d[0].set_str(G2_GEN_Y_D0, 10); - g2.y.d[1].set_str(G2_GEN_Y_D1, 10); - g2.z.d[0].set_int(1); - g2.z.d[1].clear(); - - g2 - } -} - -impl ops::Mul<&Fr> for &G2 { - type Output = G2; - fn mul(self, rhs: &Fr) -> Self::Output { - let mut g2 = G2::default(); - G2::mul(&mut g2, self, rhs); - - g2 - } -} - -impl ops::Sub for G2 { - type Output = G2; - fn sub(self, rhs: G2) -> Self::Output { - let mut g2 = G2::default(); - G2::sub(&mut g2, &self, &rhs); - - g2 - } -} - -impl Fr { - pub fn one() -> Fr { - Fr::from_int(1) - } - - pub fn get_neg(&self) -> Fr { - let mut fr = Fr::default(); - Fr::neg(&mut fr, self); - - fr - } - - pub fn get_inv(&self) -> Fr { - let mut fr = Fr::default(); - Fr::inv(&mut fr, self); - - fr - } - - pub fn random() -> Fr { - let mut fr = Fr::default(); - Fr::set_by_csprng(&mut fr); - - fr - } -} - -impl ops::Mul for Fr { - type Output = Fr; - fn mul(self, rhs: Fr) -> Self::Output { - let mut result = Fr::default(); - Fr::mul(&mut result, &self, &rhs); - - result - } -} - -impl ops::Div for Fr { - type Output = Fr; - fn div(self, rhs: Fr) -> Self::Output { - let mut result = Fr::default(); - Fr::div(&mut result, &self, &rhs); - - result - } -} - -impl ops::Sub for Fr { - type Output = Fr; - fn sub(self, rhs: Fr) -> Self::Output { - let mut result = Fr::default(); - Fr::sub(&mut result, &self, &rhs); - - result - } -} - -impl ops::Add for Fr { - type Output = Fr; - fn add(self, rhs: Fr) -> Self::Output { - let mut result = Fr::default(); - Fr::add(&mut result, &self, &rhs); - - result - } -} - -// KZG 10 Impl - -#[derive(Debug, Clone, PartialEq, Default)] -pub struct Polynomial { - pub coeffs: Vec, -} - -impl Polynomial { - pub fn new(size: usize) -> Self { - Polynomial { - coeffs: vec![Fr::default(); size], - } - } - - pub fn from_fr(data: Vec) -> Self { - Self { coeffs: data } - } - - pub fn from_i32(data: &[i32]) -> Self { - Self { - coeffs: data.iter().map(|x| Fr::from_int(*x)).collect(), - } - } - - pub fn order(&self) -> usize { - self.coeffs.len() - } - - pub fn eval_at(&self, point: &Fr) -> Fr { - let mut result = Fr::default(); - unsafe { - mclBn_FrEvaluatePolynomial(&mut result, self.coeffs.as_ptr(), self.order(), point) - }; - result - } - - pub fn gen_proof_at(&self, g1_points: &[G1], point: &Fr) -> Result { - let divisor = vec![point.get_neg(), Fr::one()]; - let quotient_poly = self.long_division(&divisor).unwrap(); - - let mut result = G1::default(); - g1_linear_combination( - &mut result, - g1_points, - quotient_poly.coeffs.as_slice(), - min(g1_points.len(), quotient_poly.order()), - ); - - Ok(result) - } - - pub fn poly_quotient_length(dividend: &[Fr], divisor: &[Fr]) -> usize { - if dividend.len() >= divisor.len() { - dividend.len() - divisor.len() + 1 - } else { - 0 - } - } - - pub fn long_division(&self, divisor: &[Fr]) -> Result { - if divisor.is_empty() { - return Err(String::from("Dividing by zero is undefined")); - } - if divisor.last().unwrap().is_zero() { - return Err(String::from( - "The divisor's highest coefficient must be non-zero", - )); - } - let out_length = Polynomial::poly_quotient_length(&self.coeffs, divisor); - if out_length == 0 { - return Ok(Polynomial::default()); - } - - let mut a_pos = self.order() - 1; - let b_pos = divisor.len() - 1; - let mut diff = a_pos - b_pos; - - let mut a = self.coeffs.clone(); - let mut out_coeffs = vec![Fr::default(); out_length]; - - while diff > 0 { - out_coeffs[diff] = a[a_pos] / divisor[b_pos]; - - for i in 0..b_pos { - // a[diff + i] -= b[i] * quot - let tmp = out_coeffs[diff] * divisor[i]; - a[diff + i] = a[diff + i] - tmp; - } - - a_pos -= 1; - diff -= 1; - } - out_coeffs[0] = a[a_pos] / divisor[b_pos]; - Ok(Polynomial::from_fr(out_coeffs)) - } - - pub fn fast_div(&self, divisor: &[Fr]) -> Result { - if divisor.is_empty() { - return Err(String::from("Dividing by zero is undefined")); - } - if divisor.last().unwrap().is_zero() { - return Err(String::from( - "The divisor's highest coefficient must be non-zero", - )); - } - let mut out_length = Polynomial::poly_quotient_length(&self.coeffs, divisor); - if out_length == 0 { - return Ok(Polynomial::default()); - } - - // Special case for divisor.length == 1 (it's a constant) - if divisor.len() == 1 { - let mut out_coeffs: Vec = vec![]; - out_length = self.order(); - for i in 0..out_length { - out_coeffs.push(self.coeffs[i] / divisor[0]); - } - return Ok(Polynomial::from_fr(out_coeffs)); - } - - let a_flip = Polynomial::from_fr(Polynomial::flip_coeffs(&self.coeffs)); - let b_flip = Polynomial::from_fr(Polynomial::flip_coeffs(divisor)); - let inv_b_flip = b_flip.inverse(out_length).unwrap(); - let q_flip = a_flip.mul(&inv_b_flip, out_length).unwrap(); - - Ok(q_flip.flip()) - } - - fn normalise_coeffs(coeffs: &[Fr]) -> Vec { - let mut ret_length = coeffs.len(); - while ret_length > 0 && coeffs[ret_length - 1].is_zero() { - ret_length -= 1; - } - coeffs[0..ret_length].to_vec() - } - - fn normalise(&self) -> Polynomial { - Polynomial::from_fr(Polynomial::normalise_coeffs(&self.coeffs)) - } - - fn flip_coeffs(coeffs: &[Fr]) -> Vec { - let mut result: Vec = vec![]; - for i in (0..coeffs.len()).rev() { - result.push(coeffs[i]); - } - result - } - - fn flip(&self) -> Polynomial { - Polynomial::from_fr(Polynomial::flip_coeffs(&self.coeffs)) - } - - pub fn div(&self, _divisor: &[Fr]) -> Result { - let dividend = self.normalise(); - let divisor = Polynomial::normalise_coeffs(_divisor); - - if divisor.len() >= dividend.order() || divisor.len() < 128 { - // Tunable paramter - self.long_division(&divisor) - } else { - self.fast_div(&divisor) - } - } - - pub fn commit(&self, g1_points: &[G1]) -> Result { - if self.order() > g1_points.len() { - return Err(String::from("Provided polynomial is longer than G1!")); - } - - let mut result = G1::default(); - g1_linear_combination( - &mut result, - g1_points, - self.coeffs.as_slice(), - min(g1_points.len(), self.order()), - ); - Ok(result) - } - - pub fn random(order: usize) -> Polynomial { - let coeffs = iter::repeat(0).take(order).map(|_| Fr::random()).collect(); - - Polynomial { coeffs } - } - - pub fn mul_( - &self, - b: &Self, - ft: Option<&FFTSettings>, - len: usize, - ) -> Result { - if self.order() < 64 || b.order() < 64 || len < 128 { - // Tunable parameter - Polynomial::mul_direct(self, b, len) - } else { - Polynomial::mul_fft(self, b, ft, len) - } - } - - pub fn mul(&self, b: &Self, len: usize) -> Result { - Polynomial::mul_(self, b, None, len) - } - - /// @param[in] n_in The number of elements of @p in to take - /// @param[in] n_out The length of @p out - pub fn pad_coeffs(coeffs: &[Fr], n_in: usize, n_out: usize) -> Vec { - let num = min(n_in, n_out); - let mut ret_coeffs: Vec = vec![]; - for item in coeffs.iter().take(num) { - ret_coeffs.push(*item); - } - for _ in num..n_out { - ret_coeffs.push(Fr::zero()); - } - ret_coeffs - } - - pub fn pad_coeffs_mut(&mut self, n_in: usize, n_out: usize) { - let num = min(n_in, n_out); - self.coeffs = self.coeffs[..num].to_vec(); - for _ in num..n_out { - self.coeffs.push(Fr::zero()); - } - } - - /// @param[in] n_in The number of elements of @p in to take - /// @param[in] n_out The length of @p out - fn pad(&self, n_in: usize, n_out: usize) -> Polynomial { - Polynomial::from_fr(Polynomial::pad_coeffs(&self.coeffs, n_in, n_out)) - } - - // #[cfg(feature = "parallel")] - pub fn mul_fft( - &self, - b: &Self, - ft: Option<&FFTSettings>, - len: usize, - ) -> Result { - // Truncate a and b so as not to do excess work for the number of coefficients required. - let a_len = min(self.order(), len); - let b_len = min(b.order(), len); - let length = next_pow_of_2(a_len + b_len - 1); - - //TO DO remove temp_fft, can't find a nice way to declare fft and only use it as ref - let temp_fft = FFTSettings::new(log_2(length) as u8); - let fft_settings = match ft { - Some(x) => x, - None => &temp_fft, - }; - let ft = fft_settings; - if length > ft.max_width { - return Err(String::from("Mul fft only good up to length < 32 bits")); - } - - let a_pad = self.pad(a_len, length); - let b_pad = b.pad(b_len, length); - let a_fft: Vec; - let b_fft: Vec; - - #[cfg(feature = "parallel")] - { - if length > 1024 { - let mut a_fft_temp = vec![]; - let mut b_fft_temp = vec![]; - - rayon::join( - || a_fft_temp = ft.fft(&a_pad.coeffs, false).unwrap(), - || b_fft_temp = ft.fft(&b_pad.coeffs, false).unwrap(), - ); - - a_fft = a_fft_temp; - b_fft = b_fft_temp; - } else { - a_fft = ft.fft(&a_pad.coeffs, false).unwrap(); - b_fft = ft.fft(&b_pad.coeffs, false).unwrap(); - } - } - #[cfg(not(feature = "parallel"))] - { - a_fft = ft.fft(&a_pad.coeffs, false).unwrap(); - b_fft = ft.fft(&b_pad.coeffs, false).unwrap(); - } - - let mut ab_fft = a_fft; - for i in 0..length { - ab_fft[i] = ab_fft[i] * b_fft[i]; - } - let ab = ft.fft(&ab_fft, true).unwrap(); - - let mut ret_coeffs: Vec = ab; - - //pad if too short, else take first len if too long - if len > length { - for _ in length..len { - ret_coeffs.push(Fr::zero()); - } - } else { - unsafe { - ret_coeffs.set_len(len); - } - } - Ok(Polynomial::from_fr(ret_coeffs)) - } - - pub fn mul_direct(&self, b: &Self, len: usize) -> Result { - let mut coeffs: Vec = vec![]; - for _ in 0..len { - coeffs.push(Fr::zero()); - } - - for i in 0..self.order() { - let mut j = 0; - while j < b.order() && i + j < len { - let temp = self.coeffs[i] * b.coeffs[j]; - coeffs[i + j] = coeffs[i + j] + temp; - j += 1; - } - } - Ok(Polynomial::from_fr(coeffs)) - } - - pub fn inverse(&self, new_length: usize) -> Result { - let self_length = self.order(); - if self_length == 0 || new_length == 0 { - return Ok(Polynomial::default()); - } - if self.coeffs[0].is_zero() { - return Err(String::from("The constant term of self must be nonzero.")); - } - - // If the input polynomial is constant, the remainder of the series is zero - if self_length == 1 { - let mut coeffs = vec![self.coeffs[0].inverse()]; - for _ in 1..new_length { - coeffs.push(Fr::zero()); - } - return Ok(Polynomial::from_fr(coeffs)); - } - - let maxd = new_length - 1; - let mut d = 0; - - // Max space for multiplications is (2 * length - 1) - //use a more efficent log_2? - let scale = log_2(next_pow_of_2(2 * new_length - 1)); - //check if scale actually always fits in u8 - //fftsettings to be used, if multiplacation is done with fft - let fs = FFTSettings::new(scale as u8); - let coeffs = vec![self.coeffs[0].inverse()]; - let mut out = Polynomial::from_fr(coeffs); - - //if new length is 1, max d is 0 - let mut mask = 1 << log_2(maxd); - while mask != 0 { - d = 2 * d + ((maxd & mask) != 0) as usize; - mask >>= 1; - - // b.c -> tmp0 (we're using out for c) - let temp_0_len = min(d + 1, self.order() + out.order() - 1); - let mut poly_temp_0: Polynomial = self.mul_(&out, Some(&fs), temp_0_len).unwrap(); - - // 2 - b.c -> tmp0 - for i in 0..temp_0_len { - poly_temp_0.coeffs[i] = poly_temp_0.coeffs[i].get_neg(); - } - - let fr_two = Fr::from_int(2); - poly_temp_0.coeffs[0] = poly_temp_0.coeffs[0] + fr_two; - - // c.(2 - b.c) -> tmp1; - let temp_1_len = d + 1; - let poly_temp_1: Polynomial = out.mul_(&poly_temp_0, Some(&fs), temp_1_len).unwrap(); - - out = Polynomial::from_fr(poly_temp_1.coeffs); - } - - if d + 1 != new_length { - return Err(String::from("d + 1 != new_length")); - } - - Ok(out) - } -} - -#[derive(Debug, Clone)] -pub struct Curve { - pub g1_gen: G1, - pub g2_gen: G2, - pub g1_points: Vec, - pub g2_points: Vec, -} - -impl Default for Curve { - fn default() -> Self { - let g1_gen = G1::gen(); - let g2_gen = G2::gen(); - let g1_points: Vec = vec![]; - let g2_points: Vec = vec![]; - - Self { - g1_gen, - g2_gen, - g1_points, - g2_points, - } - } -} - -impl Curve { - pub fn new(secret: &Fr, order: usize) -> Self { - let g1_gen = G1::gen(); - let g2_gen = G2::gen(); - - let mut g1_points = vec![G1::default(); order]; - let mut g2_points = vec![G2::default(); order]; - - let mut secret_to_power = Fr::one(); - for i in 0..order { - G1::mul(&mut (g1_points[i]), &g1_gen, &secret_to_power); - G2::mul(&mut (g2_points[i]), &g2_gen, &secret_to_power); - - secret_to_power *= secret; - } - - Self { - g1_gen, - g2_gen, - g1_points, - g2_points, - } - } - - pub fn new2(secret_g1: &[G1], secret_g2: &[G2], order: usize) -> Self { - let g1_gen = G1::gen(); - let g2_gen = G2::gen(); - - let mut g1_points: Vec = vec![]; - let mut g2_points: Vec = vec![]; - for i in 0..order { - g1_points.push(secret_g1[i]); - g2_points.push(secret_g2[i]); - } - - Self { - g1_gen, - g2_gen, - g1_points, - g2_points, - } - } - - pub fn is_proof_valid(&self, commitment: &G1, proof: &G1, x: &Fr, y: &Fr) -> bool { - let secret_minus_x = self.g2_points[1] - (&self.g2_gen * x); // g2 * x to get x on g2 - let commitment_minus_y = commitment - &(self.g1_gen * y); - Curve::verify_pairing(&commitment_minus_y, &self.g2_gen, proof, &secret_minus_x) - } - - #[cfg(not(feature = "parallel"))] - pub fn verify_pairing(a1: &G1, a2: &G2, b1: &G1, b2: &G2) -> bool { - let pairing1 = a1.pair(a2).get_inv(); - let pairing2 = b1.pair(b2); - let result = (pairing1 * pairing2).get_final_exp(); - result.is_one() - } - - #[cfg(feature = "parallel")] - pub fn verify_pairing(a1: &G1, a2: &G2, b1: &G1, b2: &G2) -> bool { - let g1 = [(a1, a2), (b1, b2)]; - - let mut pairings = g1 - .par_iter() - .map(|(v1, v2)| v1.pair(v2)) - .collect::>(); - let result = (pairings.pop().unwrap() * pairings.pop().unwrap().get_inv()).get_final_exp(); - - result.is_one() - } -} diff --git a/mcl/kzg/src/kzg_settings.rs b/mcl/kzg/src/kzg_settings.rs deleted file mode 100644 index 1e6dbbe97..000000000 --- a/mcl/kzg/src/kzg_settings.rs +++ /dev/null @@ -1,131 +0,0 @@ -use crate::data_types::{fr::Fr, g1::G1, g2::G2}; -use crate::fk20_fft::FFTSettings; -use crate::kzg10::Curve; -use crate::kzg10::Polynomial; -use kzg::common_utils::is_power_of_2; - -#[derive(Debug, Clone, Default)] -pub struct KZGSettings { - pub fft_settings: FFTSettings, - pub curve: Curve, -} - -impl KZGSettings { - pub fn new_from_curve(curve: &Curve, fft_settings: &FFTSettings) -> Self { - KZGSettings { - fft_settings: fft_settings.clone(), - curve: curve.clone(), - } - } - - pub fn new( - secret_g1: &[G1], - secret_g2: &[G2], - length: usize, - fft_settings: &FFTSettings, - ) -> Result { - if length < fft_settings.max_width { - return Err(String::from( - "length must be equal to or greater than fft settings max width", - )); - } - if secret_g1.len() < fft_settings.max_width { - return Err(String::from( - "secret g1 must have a length equal to or greater than fft settings max width", - )); - } - if secret_g2.len() < fft_settings.max_width { - return Err(String::from( - "secret g2 must have a length equal to or greater than fft settings max width", - )); - } - - let mut secret1: Vec = vec![]; - let mut secret2: Vec = vec![]; - for i in 0..length { - secret1.push(secret_g1[i]); - secret2.push(secret_g2[i]); - } - let curve = Curve::new2(&secret1, &secret2, length); - - Ok(KZGSettings { - fft_settings: fft_settings.clone(), - curve, - }) - } - - pub fn check_proof_single(&self, commitment: &G1, proof: &G1, x: &Fr, y: &Fr) -> bool { - self.curve.is_proof_valid(commitment, proof, x, y) - } - - pub fn compute_proof_multi(&self, p: &Polynomial, x0: &Fr, n: usize) -> Result { - if !is_power_of_2(n) { - return Err(String::from("n must be a power of 2")); - } - - let mut divisor = Polynomial::from_fr(vec![]); - let x_pow_n = x0.pow(n); - divisor.coeffs.push(x_pow_n.get_neg()); - - for _ in 1..n { - divisor.coeffs.push(Fr::zero()); - } - - divisor.coeffs.push(Fr::one()); - let temp_poly = p.clone(); - let q = temp_poly.div(&divisor.coeffs).unwrap(); - Ok(q.commit(&self.curve.g1_points).unwrap()) - } - - pub fn check_proof_multi( - &self, - commitment: &G1, - proof: &G1, - x: &Fr, - ys: &[Fr], - n: usize, - ) -> Result { - if !is_power_of_2(n) { - return Err(String::from("n must be a power of 2")); - } - - let mut interpolation_poly = Polynomial::new(n); - interpolation_poly.coeffs = self.fft_settings.fft(ys, true).unwrap(); - - let inv_x = x.inverse(); - let mut inv_x_pow = inv_x; - for i in 1..n { - interpolation_poly.coeffs[i] = interpolation_poly.coeffs[i] * inv_x_pow; - inv_x_pow = inv_x_pow * inv_x; - } - - let x_pow = inv_x_pow.inverse(); - let xn2 = &self.curve.g2_gen * &x_pow; - let xn_minus_yn = self.curve.g2_points[n] - xn2; - let is1 = interpolation_poly.commit(&self.curve.g1_points).unwrap(); - let commit_minus_interp = commitment - &is1; - Ok(Curve::verify_pairing( - &commit_minus_interp, - &self.curve.g2_gen, - proof, - &xn_minus_yn, - )) - } - - pub fn generate_trusted_setup(n: usize, secret: [u8; 32usize]) -> (Vec, Vec) { - let g1_gen = G1::gen(); - let g2_gen = G2::gen(); - - let mut g1_points = vec![G1::default(); n]; - let mut g2_points = vec![G2::default(); n]; - let secretfr = Fr::from_bytes(&secret); - let mut secret_to_power = Fr::one(); - for i in 0..n { - g1_points[i] = &g1_gen * &secret_to_power; - g2_points[i] = &g2_gen * &secret_to_power; - secret_to_power *= secretfr.as_ref().unwrap(); - } - - (g1_points, g2_points) - } -} diff --git a/mcl/kzg/src/lib.rs b/mcl/kzg/src/lib.rs deleted file mode 100644 index 8ca00e002..000000000 --- a/mcl/kzg/src/lib.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::os::raw::c_int; - -pub type BlstPairing = blst::Pairing; -pub type BlstFp = blst::blst_fp; -pub type BlstFp2 = blst::blst_fp2; -pub type BlstFp12 = blst::blst_fp12; -pub type BlstFp6 = blst::blst_fp6; -pub type BlstFr = blst::blst_fr; -pub type BlstP1 = blst::blst_p1; -pub type BlstP1Affine = blst::blst_p1_affine; -pub type BlstP2 = blst::blst_p2; -pub type BlstP2Affine = blst::blst_p2_affine; -pub type BlstScalar = blst::blst_scalar; -pub type BlstUniq = blst::blst_uniq; - -pub enum CurveType { - BN254 = 0, - BN381 = 1, - SNARK = 4, - BLS12_381 = 5, -} - -const MCLBN_FP_UNIT_SIZE: usize = 6; -const MCLBN_FR_UNIT_SIZE: usize = 4; -const MCLBN_COMPILED_TIME_VAR: c_int = - MCLBN_FR_UNIT_SIZE as c_int * 10 + MCLBN_FP_UNIT_SIZE as c_int; - -#[macro_use] -pub mod init_def; -pub mod mcl_methods; -pub mod utilities; -pub mod data_types { - pub mod fp; - pub mod fp2; - pub mod fr; - pub mod g1; - pub mod g2; - pub mod gt; -} -pub mod trait_implementations { - pub mod das; - pub mod fft_fr; - pub mod fft_g1; - pub mod fft_settings; - pub mod fk20; - pub mod fr; - pub mod g1; - pub mod g2; - pub mod kzg_settings; - pub mod poly; - pub mod zero_poly; -} -pub mod c_bindings; -pub mod das; -pub mod data_recovery; -pub mod eip_4844; -pub mod fk20_fft; -pub mod fk20_matrix; -pub mod kzg10; -pub mod kzg_settings; -pub mod zero_poly; diff --git a/mcl/kzg/src/mcl_methods.rs b/mcl/kzg/src/mcl_methods.rs deleted file mode 100644 index b1c36e63a..000000000 --- a/mcl/kzg/src/mcl_methods.rs +++ /dev/null @@ -1,88 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::data_types::g1::G1; -use crate::data_types::g2::G2; -use crate::data_types::gt::GT; -use crate::CurveType; -use std::os::raw::c_int; - -#[link(name = "mcl", kind = "static")] -#[link(name = "mclbn384_256", kind = "static")] -#[link(name = "stdc++")] -#[allow(non_snake_case)] -extern "C" { - // global functions - pub fn mclBn_init(curve: c_int, compiledTimeVar: c_int) -> c_int; - pub fn mclBn_getVersion() -> u32; - pub fn mclBn_getFrByteSize() -> u32; - pub fn mclBn_getFpByteSize() -> u32; - pub fn mclBn_getCurveOrder(buf: *mut u8, maxBufSize: usize) -> usize; - pub fn mclBn_getFieldOrder(buf: *mut u8, maxBufSize: usize) -> usize; - pub fn mclBn_pairing(z: *mut GT, x: *const G1, y: *const G2); - pub fn mclBn_millerLoop(z: *mut GT, x: *const G1, y: *const G2); - pub fn mclBn_finalExp(y: *mut GT, x: *const GT); - pub fn mclBn_FrEvaluatePolynomial( - result: *mut Fr, - poly: *const Fr, - bufSize: usize, - x: *const Fr, - ); - pub fn mclBn_setETHserialization(v: i32); -} - -pub fn get_version() -> u32 { - unsafe { mclBn_getVersion() } -} - -pub fn set_eth_serialization(v: i32) { - unsafe { mclBn_setETHserialization(v) } -} - -pub fn init(curve: CurveType) -> bool { - unsafe { mclBn_init(curve as c_int, crate::MCLBN_COMPILED_TIME_VAR) == 0 } -} - -pub fn get_fr_serialized_size() -> u32 { - unsafe { mclBn_getFrByteSize() } -} - -pub fn get_fp_serialized_size() -> u32 { - unsafe { mclBn_getFpByteSize() } -} - -pub fn get_g1_serialized_size() -> u32 { - get_fp_serialized_size() -} - -pub fn get_g2_serialized_size() -> u32 { - get_fp_serialized_size() * 2 -} - -pub fn get_gt_serialized_size() -> u32 { - get_fp_serialized_size() * 12 -} - -pub fn get_field_order() -> String { - get_str_impl![mclBn_getFieldOrder] -} - -pub fn get_curve_order() -> String { - get_str_impl![mclBn_getCurveOrder] -} - -pub fn pairing(z: &mut GT, x: &G1, y: &G2) { - unsafe { - mclBn_pairing(z, x, y); - } -} - -pub fn miller_loop(z: &mut GT, x: &G1, y: &G2) { - unsafe { - mclBn_millerLoop(z, x, y); - } -} - -pub fn final_exp(y: &mut GT, x: >) { - unsafe { - mclBn_finalExp(y, x); - } -} diff --git a/mcl/kzg/src/trait_implementations/das.rs b/mcl/kzg/src/trait_implementations/das.rs deleted file mode 100644 index f0f593f48..000000000 --- a/mcl/kzg/src/trait_implementations/das.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::fk20_fft::FFTSettings; -use kzg::DAS as Das; - -impl Das for FFTSettings { - fn das_fft_extension(&self, evens: &[Fr]) -> Result, String> { - let mut values = evens.to_vec(); - FFTSettings::das_fft_extension(self, &mut values).unwrap(); - Ok(values) - } -} diff --git a/mcl/kzg/src/trait_implementations/fft_fr.rs b/mcl/kzg/src/trait_implementations/fft_fr.rs deleted file mode 100644 index cd551426b..000000000 --- a/mcl/kzg/src/trait_implementations/fft_fr.rs +++ /dev/null @@ -1,9 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::fk20_fft::FFTSettings; -use kzg::FFTFr; - -impl FFTFr for FFTSettings { - fn fft_fr(&self, data: &[Fr], inverse: bool) -> Result, String> { - FFTSettings::fft(self, data, inverse) - } -} diff --git a/mcl/kzg/src/trait_implementations/fft_g1.rs b/mcl/kzg/src/trait_implementations/fft_g1.rs deleted file mode 100644 index 543062d93..000000000 --- a/mcl/kzg/src/trait_implementations/fft_g1.rs +++ /dev/null @@ -1,13 +0,0 @@ -use crate::data_types::g1::G1; -use crate::fk20_fft::FFTSettings; -use kzg::FFTG1 as FftG1; - -impl FftG1 for FFTSettings { - fn fft_g1(&self, data: &[G1], inverse: bool) -> Result, String> { - if inverse { - FFTSettings::fft_g1_inv(self, data) - } else { - FFTSettings::fft_g1(self, data) - } - } -} diff --git a/mcl/kzg/src/trait_implementations/fft_settings.rs b/mcl/kzg/src/trait_implementations/fft_settings.rs deleted file mode 100644 index 5b96fc4f0..000000000 --- a/mcl/kzg/src/trait_implementations/fft_settings.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::fk20_fft::{FFTSettings, SCALE_2_ROOT_OF_UNITY_PR7_STRINGS}; -use kzg::FFTSettings as CommonFFTSettings; - -impl CommonFFTSettings for FFTSettings { - fn new(scale: usize) -> Result { - //currently alawys use PR 7 for shared tests - FFTSettings::new_custom_primitive_roots(scale as u8, SCALE_2_ROOT_OF_UNITY_PR7_STRINGS) - } - - fn get_max_width(&self) -> usize { - self.max_width - } - - fn get_expanded_roots_of_unity_at(&self, i: usize) -> Fr { - self.expanded_roots_of_unity[i] - } - - fn get_expanded_roots_of_unity(&self) -> &[Fr] { - &self.expanded_roots_of_unity - } - - fn get_reverse_roots_of_unity_at(&self, i: usize) -> Fr { - self.reverse_roots_of_unity[i] - } - - fn get_reversed_roots_of_unity(&self) -> &[Fr] { - &self.reverse_roots_of_unity - } - - fn get_roots_of_unity_at(&self, i: usize) -> Fr { - self.roots_of_unity[i] - } - - fn get_roots_of_unity(&self) -> &[Fr] { - &self.roots_of_unity - } -} diff --git a/mcl/kzg/src/trait_implementations/fk20.rs b/mcl/kzg/src/trait_implementations/fk20.rs deleted file mode 100644 index a2800a99a..000000000 --- a/mcl/kzg/src/trait_implementations/fk20.rs +++ /dev/null @@ -1,34 +0,0 @@ -use crate::data_types::{fr::Fr, g1::G1, g2::G2}; -use crate::fk20_fft::FFTSettings; -use crate::fk20_matrix::{FK20Matrix, FK20SingleMatrix}; -use crate::kzg10::Polynomial; -use crate::kzg_settings::KZGSettings; -use kzg::{FK20MultiSettings, FK20SingleSettings}; - -impl FK20SingleSettings for FK20SingleMatrix { - fn new(ks: &KZGSettings, n2: usize) -> Result { - FK20SingleMatrix::new(ks, n2) - } - - fn data_availability(&self, p: &Polynomial) -> Result, String> { - self.dau_using_fk20_single(p) - } - - fn data_availability_optimized(&self, p: &Polynomial) -> Result, String> { - self.fk20_single_dao_optimized(p) - } -} - -impl FK20MultiSettings for FK20Matrix { - fn new(ks: &KZGSettings, n2: usize, chunk_len: usize) -> Result { - FK20Matrix::new(ks, n2, chunk_len) - } - - fn data_availability(&self, p: &Polynomial) -> Result, String> { - self.dau_using_fk20_multi(p) - } - - fn data_availability_optimized(&self, p: &Polynomial) -> Result, String> { - self.fk20_multi_dao_optimized(p) - } -} diff --git a/mcl/kzg/src/trait_implementations/fr.rs b/mcl/kzg/src/trait_implementations/fr.rs deleted file mode 100644 index 07ae5056c..000000000 --- a/mcl/kzg/src/trait_implementations/fr.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::data_types::fr::Fr; -use kzg::eip_4844::BYTES_PER_FIELD_ELEMENT; -use kzg::Fr as CommonFr; - -impl CommonFr for Fr { - fn null() -> Self { - Fr::from_u64_arr(&[u64::MAX, u64::MAX, u64::MAX, u64::MAX / 3]) - } - - fn zero() -> Self { - Fr::zero() - } - - fn one() -> Self { - Fr::from_int(1) - } - - fn rand() -> Self { - Fr::random() - } - - fn from_bytes(bytes: &[u8]) -> Result { - bytes - .try_into() - .map_err(|_| { - format!( - "Invalid byte length. Expected {}, got {}", - BYTES_PER_FIELD_ELEMENT, - bytes.len() - ) - }) - .and_then(|bytes: &[u8; BYTES_PER_FIELD_ELEMENT]| Self::from_bytes(bytes)) - } - - fn from_hex(hex: &str) -> Result { - let bytes = hex::decode(&hex[2..]).unwrap(); - Self::from_bytes(&bytes) - } - - fn from_u64_arr(u: &[u64; 4]) -> Self { - Fr::from_u64_arr(u) - } - - fn from_u64(val: u64) -> Self { - Fr::from_u64_arr(&[val, 0, 0, 0]) - } - - fn to_bytes(&self) -> [u8; 32] { - Self::to_bytes(self) - } - - fn to_u64_arr(&self) -> [u64; 4] { - Fr::to_u64_arr(self) - } - - fn is_one(&self) -> bool { - Fr::is_one(self) - } - - fn is_zero(&self) -> bool { - Fr::is_zero(self) - } - - fn is_null(&self) -> bool { - let temp = Fr::null(); - self.equals(&temp) - } - - fn sqr(&self) -> Self { - let mut res = Fr::zero(); - Fr::sqr(&mut res, self); - res - } - - fn mul(&self, b: &Self) -> Self { - let mut res = Fr::zero(); - Fr::mul(&mut res, self, b); - res - } - - fn add(&self, b: &Self) -> Self { - let mut res = Fr::zero(); - Fr::add(&mut res, self, b); - res - } - - fn sub(&self, b: &Self) -> Self { - let mut res = Fr::zero(); - Fr::sub(&mut res, self, b); - res - } - - fn eucl_inverse(&self) -> Self { - todo!() - } - - fn negate(&self) -> Self { - self.get_neg() - } - - fn inverse(&self) -> Self { - self.inverse() - } - - fn pow(&self, n: usize) -> Self { - Fr::pow(self, n) - } - - fn div(&self, b: &Self) -> Result { - let mut res = Fr::zero(); - Fr::div(&mut res, self, b); - Ok(res) - } - - fn equals(&self, b: &Self) -> bool { - Fr::eq(self, b) - } -} diff --git a/mcl/kzg/src/trait_implementations/g1.rs b/mcl/kzg/src/trait_implementations/g1.rs deleted file mode 100644 index 2073cb081..000000000 --- a/mcl/kzg/src/trait_implementations/g1.rs +++ /dev/null @@ -1,102 +0,0 @@ -use crate::data_types::g1::is_valid_order; -use crate::data_types::{fr::Fr, g1::G1}; -use crate::fk20_fft::{G1_GENERATOR, G1_NEGATIVE_GENERATOR}; -use crate::mcl_methods::set_eth_serialization; -use kzg::eip_4844::BYTES_PER_G1; -use kzg::{G1Mul, G1 as CommonG1}; - -impl CommonG1 for G1 { - fn identity() -> Self { - G1::G1_IDENTITY - } - - fn generator() -> Self { - G1_GENERATOR - } - - fn negative_generator() -> Self { - G1_NEGATIVE_GENERATOR - } - - fn rand() -> Self { - G1::random() - } - - fn from_bytes(bytes: &[u8]) -> Result { - bytes - .try_into() - .map_err(|_| { - format!( - "Invalid byte length. Expected {}, got {}", - BYTES_PER_G1, - bytes.len() - ) - }) - .and_then(|bytes: &[u8; BYTES_PER_G1]| { - set_eth_serialization(1); - let mut g1 = G1::default(); - if !G1::deserialize(&mut g1, bytes) { - return Err("Failed to deserialize".to_string()); - } - Ok(g1) - }) - } - - fn from_hex(hex: &str) -> Result { - let bytes = hex::decode(&hex[2..]).unwrap(); - Self::from_bytes(&bytes) - } - - fn to_bytes(&self) -> [u8; 48] { - set_eth_serialization(1); - G1::serialize(self).try_into().unwrap() - } - - fn add_or_dbl(&mut self, b: &Self) -> Self { - let mut g1 = G1::zero(); - if self == b { - G1::dbl(&mut g1, self); - } else { - G1::add(&mut g1, self, b); - } - g1 - } - - fn is_inf(&self) -> bool { - G1::eq(self, &G1::G1_IDENTITY) - } - - fn is_valid(&self) -> bool { - self.is_valid() && is_valid_order(self) - } - - fn dbl(&self) -> Self { - let mut g1 = G1::zero(); - G1::dbl(&mut g1, self); - g1 - } - - fn add(&self, b: &Self) -> Self { - let mut g1 = G1::zero(); - G1::add(&mut g1, self, b); - g1 - } - - fn sub(&self, b: &Self) -> Self { - let mut g1 = G1::zero(); - G1::sub(&mut g1, self, b); - g1 - } - - fn equals(&self, b: &Self) -> bool { - G1::eq(self, b) - } -} - -impl G1Mul for G1 { - fn mul(&self, b: &Fr) -> Self { - let mut g1 = G1::zero(); - G1::mul(&mut g1, self, b); - g1 - } -} diff --git a/mcl/kzg/src/trait_implementations/g2.rs b/mcl/kzg/src/trait_implementations/g2.rs deleted file mode 100644 index b074a214b..000000000 --- a/mcl/kzg/src/trait_implementations/g2.rs +++ /dev/null @@ -1,73 +0,0 @@ -use crate::data_types::{fr::Fr, g2::G2}; -use crate::mcl_methods::set_eth_serialization; -use kzg::eip_4844::BYTES_PER_G2; -use kzg::{G2Mul, G2 as CommonG2}; - -impl CommonG2 for G2 { - fn generator() -> Self { - G2::gen() - } - - fn negative_generator() -> Self { - G2::G2_NEGATIVE_GENERATOR - } - - fn from_bytes(bytes: &[u8]) -> Result { - bytes - .try_into() - .map_err(|_| { - format!( - "Invalid byte length. Expected {}, got {}", - BYTES_PER_G2, - bytes.len() - ) - }) - .and_then(|bytes: &[u8; BYTES_PER_G2]| { - set_eth_serialization(1); - let mut g2 = G2::default(); - if !G2::deserialize(&mut g2, bytes) { - return Err("Failed to deserialize".to_string()); - } - Ok(g2) - }) - } - - fn to_bytes(&self) -> [u8; 96] { - set_eth_serialization(1); - G2::serialize(self).try_into().unwrap() - } - - fn add_or_dbl(&mut self, b: &Self) -> Self { - let mut g2 = G2::zero(); - if self == b { - G2::dbl(&mut g2, self); - } else { - G2::add(&mut g2, self, b); - } - g2 - } - - fn dbl(&self) -> Self { - let mut g2 = G2::zero(); - G2::dbl(&mut g2, self); - g2 - } - - fn sub(&self, b: &Self) -> Self { - let mut g2 = G2::zero(); - G2::sub(&mut g2, self, b); - g2 - } - - fn equals(&self, b: &Self) -> bool { - G2::eq(self, b) - } -} - -impl G2Mul for G2 { - fn mul(&self, b: &Fr) -> Self { - let mut g1 = G2::zero(); - G2::mul(&mut g1, self, b); - g1 - } -} diff --git a/mcl/kzg/src/trait_implementations/kzg_settings.rs b/mcl/kzg/src/trait_implementations/kzg_settings.rs deleted file mode 100644 index 7d1df23ac..000000000 --- a/mcl/kzg/src/trait_implementations/kzg_settings.rs +++ /dev/null @@ -1,51 +0,0 @@ -use crate::data_types::{fr::Fr, g1::G1, g2::G2}; -use crate::fk20_fft::FFTSettings; -use crate::kzg10::Polynomial; -use crate::kzg_settings::KZGSettings; -use kzg::KZGSettings as CommonKZGSettings; - -impl CommonKZGSettings for KZGSettings { - fn new( - secret_g1: &[G1], - secret_g2: &[G2], - length: usize, - fs: &FFTSettings, - ) -> Result { - KZGSettings::new(secret_g1, secret_g2, length, fs) - } - - fn commit_to_poly(&self, polynomial: &Polynomial) -> Result { - polynomial.commit(&self.curve.g1_points) - } - - fn compute_proof_single(&self, polynomial: &Polynomial, x: &Fr) -> Result { - polynomial.gen_proof_at(&self.curve.g1_points, x) - } - - fn check_proof_single(&self, com: &G1, proof: &G1, x: &Fr, value: &Fr) -> Result { - Ok(KZGSettings::check_proof_single(self, com, proof, x, value)) - } - - fn compute_proof_multi(&self, p: &Polynomial, x: &Fr, n: usize) -> Result { - KZGSettings::compute_proof_multi(self, p, x, n) - } - - fn check_proof_multi( - &self, - com: &G1, - proof: &G1, - x: &Fr, - values: &[Fr], - n: usize, - ) -> Result { - KZGSettings::check_proof_multi(self, com, proof, x, values, n) - } - - fn get_expanded_roots_of_unity_at(&self, i: usize) -> Fr { - self.fft_settings.expanded_roots_of_unity[i] - } - - fn get_roots_of_unity_at(&self, i: usize) -> Fr { - self.fft_settings.roots_of_unity[i] - } -} diff --git a/mcl/kzg/src/trait_implementations/poly.rs b/mcl/kzg/src/trait_implementations/poly.rs deleted file mode 100644 index a627e5fd5..000000000 --- a/mcl/kzg/src/trait_implementations/poly.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::fk20_fft::FFTSettings; -use crate::kzg10::Polynomial; -use kzg::FFTSettingsPoly; -use kzg::Poly; -use kzg::PolyRecover; - -impl Poly for Polynomial { - fn new(size: usize) -> Result { - Ok(Polynomial::new(size)) - } - - fn get_coeff_at(&self, i: usize) -> Fr { - self.coeffs[i] - } - - fn set_coeff_at(&mut self, i: usize, x: &Fr) { - self.coeffs[i] = *x; - } - - fn get_coeffs(&self) -> &[Fr] { - &self.coeffs - } - - fn len(&self) -> usize { - Polynomial::order(self) - } - - fn eval(&self, x: &Fr) -> Fr { - Polynomial::eval_at(self, x) - } - - fn scale(&mut self) { - todo!() - } - - fn unscale(&mut self) { - todo!() - } - - fn inverse(&mut self, new_len: usize) -> Result { - Polynomial::inverse(self, new_len) - } - - fn div(&mut self, x: &Self) -> Result { - Polynomial::div(self, &x.coeffs) - } - - fn long_div(&mut self, x: &Self) -> Result { - Polynomial::long_division(self, &x.coeffs) - } - - fn fast_div(&mut self, x: &Self) -> Result { - Polynomial::fast_div(self, &x.coeffs) - } - - fn mul_direct(&mut self, x: &Self, len: usize) -> Result { - Polynomial::mul_direct(self, x, len) - } -} - -impl FFTSettingsPoly for FFTSettings { - fn poly_mul_fft( - a: &Polynomial, - x: &Polynomial, - len: usize, - fs: Option<&FFTSettings>, - ) -> Result { - Polynomial::mul_fft(a, x, fs, len) - } -} - -impl PolyRecover for Polynomial { - fn recover_poly_coeffs_from_samples( - samples: &[Option], - fs: &FFTSettings, - ) -> Result { - Polynomial::recover_coeffs_from_samples(fs, samples) - } - fn recover_poly_from_samples(samples: &[Option], fs: &FFTSettings) -> Result { - Polynomial::recover_from_samples(fs, samples) - } -} diff --git a/mcl/kzg/src/trait_implementations/zero_poly.rs b/mcl/kzg/src/trait_implementations/zero_poly.rs deleted file mode 100644 index 0220f296b..000000000 --- a/mcl/kzg/src/trait_implementations/zero_poly.rs +++ /dev/null @@ -1,30 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::fk20_fft::FFTSettings; -use crate::kzg10::Polynomial; -use kzg::ZeroPoly; - -impl ZeroPoly for FFTSettings { - fn do_zero_poly_mul_partial( - &self, - idxs: &[usize], - stride: usize, - ) -> Result { - self.do_zero_poly_mul_partial(idxs, stride) - } - - fn reduce_partials( - &self, - domain_size: usize, - partials: &[Polynomial], - ) -> Result { - self.reduce_partials(domain_size, partials) - } - - fn zero_poly_via_multiplication( - &self, - domain_size: usize, - missing_idxs: &[usize], - ) -> Result<(Vec, Polynomial), String> { - self.zero_poly_via_multiplication(domain_size, missing_idxs) - } -} diff --git a/mcl/kzg/src/utilities.rs b/mcl/kzg/src/utilities.rs deleted file mode 100644 index e3d2f0b7f..000000000 --- a/mcl/kzg/src/utilities.rs +++ /dev/null @@ -1,5 +0,0 @@ -use primitive_types::U512; - -pub fn arr64_6_to_g1_sum(u: &[u64; 6]) -> U512 { - U512([u[0], u[1], u[2], u[3], u[4], u[5], 0, 0]) -} diff --git a/mcl/kzg/src/zero_poly.rs b/mcl/kzg/src/zero_poly.rs deleted file mode 100644 index 31da2c269..000000000 --- a/mcl/kzg/src/zero_poly.rs +++ /dev/null @@ -1,218 +0,0 @@ -use crate::data_types::fr::Fr; -use crate::fk20_fft::FFTSettings; -use crate::kzg10::Polynomial; -use kzg::common_utils::{is_power_of_2, next_pow_of_2}; -use std::cmp::min; - -/// Copy all of the coefficients of polynomial @p p to @p out, padding to length @p p_len with zeros. -pub fn pad_poly(new_length: usize, poly: &Polynomial) -> Result, String> { - if new_length < poly.order() { - return Err(String::from( - "new_length must not be shorter then given poly's length", - )); - } - - let mut ret = poly.coeffs.to_vec(); - - for _ in poly.order()..new_length { - ret.push(Fr::zero()) - } - - Ok(ret) -} - -impl FFTSettings { - /// Calculates the minimal polynomial that evaluates to zero for powers of roots of unity at the given indices. - /// The returned polynomial has a length of `idxs.len() + 1`. - /// - /// Uses straightforward long multiplication to calculate the product of `(x - r^i)` where `r` is a root of unity - /// and the `i`s are the indices at which it must evaluate to zero. - pub fn do_zero_poly_mul_partial( - &self, - indices: &[usize], - stride: usize, - ) -> Result { - if indices.is_empty() { - return Err(String::from("Missing indices array must not be empty")); - } - - let mut poly = Polynomial::from_fr(vec![Fr::one(); indices.len() + 1]); - poly.coeffs[0] = self.expanded_roots_of_unity[indices[0] * stride].get_neg(); - - for (i, item) in indices.iter().enumerate().skip(1) { - poly.coeffs[i] = self.expanded_roots_of_unity[item * stride].get_neg(); - let neg_di = poly.coeffs[i]; - poly.coeffs[i] = poly.coeffs[i] + poly.coeffs[i - 1]; - for j in (1..i).rev() { - poly.coeffs[j] = poly.coeffs[j] * neg_di + poly.coeffs[j - 1]; - } - - poly.coeffs[0] = poly.coeffs[0] * neg_di; - } - - Ok(poly) - } - - /// Reduce partials using a specified domain size. - /// Calculates the product of all polynomials via FFT and then applies an inverse FFT to produce a new Polynomial. - pub fn reduce_partials( - &self, - len_out: usize, - partials: &[Polynomial], - ) -> Result { - if !is_power_of_2(len_out) { - return Err(String::from("len out must be a power of two")); - } - - // The degree of the output polynomial is the sum of the degrees of the input polynomials. - let mut out_degree: usize = 0; - for item in partials { - out_degree += item.order() - 1; - } - - if out_degree + 1 > len_out { - return Err(String::from("Out degree is longer than out len")); - } - - // Do the last partial first: it is no longer than the others and the padding can remain in place for the rest. - let mut partial_padded = pad_poly(len_out, &partials[partials.len() - 1]).unwrap(); - let mut eval_result = self.fft(&partial_padded, false).unwrap(); - - for item in partials.iter().take(partials.len() - 1) { - partial_padded = pad_poly(len_out, item).unwrap(); - let evaluated_partial = self.fft(&partial_padded, false).unwrap(); - - for j in 0..len_out { - eval_result[j] = eval_result[j] * evaluated_partial[j]; - } - } - - let coeffs = self.fft(&eval_result, true).unwrap(); - let ret = Polynomial::from_fr(coeffs[..(out_degree + 1)].to_vec()); - - Ok(ret) - } - /// Calculate the minimal polynomial that evaluates to zero for powers of roots of unity that correspond to missing - /// indices. - /// This is done simply by multiplying together `(x - r^i)` for all the `i` that are missing indices, using a - /// combination of direct multiplication ([`Self::do_zero_poly_mul_partial()`]) and iterated multiplication via - /// convolution (#reduce_partials). - /// Also calculates the FFT (the "evaluation polynomial"). - pub fn zero_poly_via_multiplication( - &self, - length: usize, - missing_indices: &[usize], - ) -> Result<(Vec, Polynomial), String> { - let zero_eval: Vec; - let mut zero_poly: Polynomial; - - if missing_indices.is_empty() { - zero_eval = vec![Fr::zero(); length]; - zero_poly = Polynomial::from_fr(vec![Fr::zero(); length]); - return Ok((zero_eval, zero_poly)); - } - - if missing_indices.len() >= length { - return Err(String::from("Missing indice count is bigger than length")); - } - if length > self.max_width { - return Err(String::from("Length is bigger than fft_settings.max_width")); - } - if !is_power_of_2(length) { - return Err(String::from("Length must be a power of 2")); - } - - let degree_of_partial = 256; // Tunable parameter. Must be a power of two. - let missing_per_partial = degree_of_partial - 1; - let domain_stride = self.max_width / length; - let mut partial_count = 1 + (missing_indices.len() - 1) / missing_per_partial; - let domain_ceiling = min(next_pow_of_2(partial_count * degree_of_partial), length); - - if missing_indices.len() <= missing_per_partial { - zero_poly = self - .do_zero_poly_mul_partial(missing_indices, domain_stride) - .unwrap(); - } else { - // Work space for building and reducing the partials - let mut work = vec![Fr::zero(); next_pow_of_2(partial_count * degree_of_partial)]; - - // Build the partials from the missing indices - // Just allocate pointers here since we're re-using `work` for the partial processing - // Combining partials can be done mostly in-place, using a scratchpad. - let mut partial_lens = vec![]; - let mut partial_offsets = vec![]; - let mut missing_offset = 0; - let mut work_offset = 0; - let max = missing_indices.len(); - - for _ in 0..partial_count { - let end = min(missing_offset + missing_per_partial, max); - - let mut partial = self - .do_zero_poly_mul_partial(&missing_indices[missing_offset..end], domain_stride) - .unwrap(); - partial.coeffs = pad_poly(degree_of_partial, &partial).unwrap(); - work.splice( - work_offset..(work_offset + degree_of_partial), - partial.coeffs.to_vec(), - ); - partial_lens.push(degree_of_partial); - partial_offsets.push(work_offset); - - missing_offset += missing_per_partial; - work_offset += degree_of_partial; - } - // Adjust the length of the last partial - partial_lens[partial_count - 1] = - 1 + missing_indices.len() - (partial_count - 1) * missing_per_partial; - - // Reduce all the partials to a single polynomial - let reduction_factor = 4; // must be a power of 2 (for sake of the FFTs in reduce_partials) - while partial_count > 1 { - let reduced_count = 1 + (partial_count - 1) / reduction_factor; - let partial_size = next_pow_of_2(partial_lens[0]); - - for i in 0..reduced_count { - let start = i * reduction_factor; - let out_end = min((start + reduction_factor) * partial_size, domain_ceiling); - let reduced_len = min(out_end - start * partial_size, length); - let partials_num = min(reduction_factor, partial_count - start); - - let mut partial_vec = Vec::new(); - partial_offsets[i] = start * partial_size; - for j in 0..(partials_num) { - partial_offsets[i + j] = (start + j) * partial_size; - partial_vec.push(Polynomial::from_fr( - work[partial_offsets[i + j] - ..(partial_offsets[i + j] + partial_lens[i + j])] - .to_vec(), - )); - } - - if partials_num > 1 { - let mut reduced_poly = - self.reduce_partials(reduced_len, &partial_vec).unwrap(); - partial_lens[i] = reduced_poly.order(); - reduced_poly.coeffs = - pad_poly(partial_size * partials_num, &reduced_poly).unwrap(); - work.splice( - (partial_offsets[i])..(partial_offsets[i] + reduced_poly.order()), - reduced_poly.coeffs, - ); - } else { - partial_lens[i] = partial_lens[start]; - } - } - - partial_count = reduced_count; - } - - zero_poly = Polynomial::from_fr(work); - } - - zero_poly.pad_coeffs_mut(zero_poly.order(), length); - zero_eval = self.fft(&zero_poly.coeffs, false).unwrap(); - - Ok((zero_eval, zero_poly)) - } -} diff --git a/mcl/src/consts.rs b/mcl/src/consts.rs new file mode 100644 index 000000000..4e43578e8 --- /dev/null +++ b/mcl/src/consts.rs @@ -0,0 +1,270 @@ +use crate::mcl_methods::{mcl_fp, mcl_fp2, mcl_g1, mcl_g2}; +use crate::types::g1::MclG1; +use crate::types::g2::MclG2; + +pub const G1_IDENTITY: MclG1 = MclG1::from_xyz( + mcl_fp { d: [0; 6] }, + mcl_fp { d: [0; 6] }, + mcl_fp { d: [0; 6] }, +); + +pub const SCALE_FACTOR: u64 = 5; + +pub const NUM_ROOTS: usize = 32; +/// The roots of unity. Every root_i equals 1 when raised to the power of (2 ^ i) +#[rustfmt::skip] +pub const SCALE2_ROOT_OF_UNITY: [[u64; 4]; 32] = [ + [0x0000000000000001, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000], + [0xffffffff00000000, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48], + [0x0001000000000000, 0xec03000276030000, 0x8d51ccce760304d0, 0x0000000000000000], + [0x7228fd3397743f7a, 0xb38b21c28713b700, 0x8c0625cd70d77ce2, 0x345766f603fa66e7], + [0x53ea61d87742bcce, 0x17beb312f20b6f76, 0xdd1c0af834cec32c, 0x20b1ce9140267af9], + [0x360c60997369df4e, 0xbf6e88fb4c38fb8a, 0xb4bcd40e22f55448, 0x50e0903a157988ba], + [0x8140d032f0a9ee53, 0x2d967f4be2f95155, 0x14a1e27164d8fdbd, 0x45af6345ec055e4d], + [0x5130c2c1660125be, 0x98d0caac87f5713c, 0xb7c68b4d7fdd60d0, 0x6898111413588742], + [0x4935bd2f817f694b, 0x0a0865a899e8deff, 0x6b368121ac0cf4ad, 0x4f9b4098e2e9f12e], + [0x4541b8ff2ee0434e, 0xd697168a3a6000fe, 0x39feec240d80689f, 0x095166525526a654], + [0x3c28d666a5c2d854, 0xea437f9626fc085e, 0x8f4de02c0f776af3, 0x325db5c3debf77a1], + [0x4a838b5d59cd79e5, 0x55ea6811be9c622d, 0x09f1ca610a08f166, 0x6d031f1b5c49c834], + [0xe206da11a5d36306, 0x0ad1347b378fbf96, 0xfc3e8acfe0f8245f, 0x564c0a11a0f704f4], + [0x6fdd00bfc78c8967, 0x146b58bc434906ac, 0x2ccddea2972e89ed, 0x485d512737b1da3d], + [0x034d2ff22a5ad9e1, 0xae4622f6a9152435, 0xdc86b01c0d477fa6, 0x56624634b500a166], + [0xfbd047e11279bb6e, 0xc8d5f51db3f32699, 0x483405417a0cbe39, 0x3291357ee558b50d], + [0xd7118f85cd96b8ad, 0x67a665ae1fcadc91, 0x88f39a78f1aeb578, 0x2155379d12180caa], + [0x08692405f3b70f10, 0xcd7f2bd6d0711b7d, 0x473a2eef772c33d6, 0x224262332d8acbf4], + [0x6f421a7d8ef674fb, 0xbb97a3bf30ce40fd, 0x652f717ae1c34bb0, 0x2d3056a530794f01], + [0x194e8c62ecb38d9d, 0xad8e16e84419c750, 0xdf625e80d0adef90, 0x520e587a724a6955], + [0xfece7e0e39898d4b, 0x2f69e02d265e09d9, 0xa57a6e07cb98de4a, 0x03e1c54bcb947035], + [0xcd3979122d3ea03a, 0x46b3105f04db5844, 0xc70d0874b0691d4e, 0x47c8b5817018af4f], + [0xc6e7a6ffb08e3363, 0xe08fec7c86389bee, 0xf2d38f10fbb8d1bb, 0x0abe6a5e5abcaa32], + [0x5616c57de0ec9eae, 0xc631ffb2585a72db, 0x5121af06a3b51e3c, 0x73560252aa0655b2], + [0x92cf4deb77bd779c, 0x72cf6a8029b7d7bc, 0x6e0bcd91ee762730, 0x291cf6d68823e687], + [0xce32ef844e11a51e, 0xc0ba12bb3da64ca5, 0x0454dc1edc61a1a3, 0x019fe632fd328739], + [0x531a11a0d2d75182, 0x02c8118402867ddc, 0x116168bffbedc11d, 0x0a0a77a3b1980c0d], + [0xe2d0a7869f0319ed, 0xb94f1101b1d7a628, 0xece8ea224f31d25d, 0x23397a9300f8f98b], + [0xd7b688830a4f2089, 0x6558e9e3f6ac7b41, 0x99e276b571905a7d, 0x52dd465e2f094256], + [0x474650359d8e211b, 0x84d37b826214abc6, 0x8da40c1ef2bb4598, 0x0c83ea7744bf1bee], + [0x694341f608c9dd56, 0xed3a181fabb30adc, 0x1339a815da8b398f, 0x2c6d4e4511657e1e], + [0x63e7cb4906ffc93f, 0xf070bb00e28a193d, 0xad1715b02e5713b5, 0x4b5371495990693f] +]; + +pub const G1_GENERATOR: MclG1 = MclG1(mcl_g1 { + x: mcl_fp { + d: [ + 0x5cb38790fd530c16, + 0x7817fc679976fff5, + 0x154f95c7143ba1c1, + 0xf0ae6acdf3d0e747, + 0xedce6ecc21dbf440, + 0x120177419e0bfb75, + ], + }, + y: mcl_fp { + d: [ + 0xbaac93d50ce72271, + 0x8c22631a7918fd8e, + 0xdd595f13570725ce, + 0x51ac582950405194, + 0x0e1c8c3fad0059c0, + 0x0bbc3efc5008a26a, + ], + }, + z: mcl_fp { + d: [ + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, + ], + }, +}); + +pub const G1_NEGATIVE_GENERATOR: MclG1 = MclG1(mcl_g1 { + x: mcl_fp { + d: [ + 0x5cb38790fd530c16, + 0x7817fc679976fff5, + 0x154f95c7143ba1c1, + 0xf0ae6acdf3d0e747, + 0xedce6ecc21dbf440, + 0x120177419e0bfb75, + ], + }, + y: mcl_fp { + d: [ + 0xff526c2af318883a, + 0x92899ce4383b0270, + 0x89d7738d9fa9d055, + 0x12caf35ba344c12a, + 0x3cff1b76964b5317, + 0x0e44d2ede9774430, + ], + }, + z: mcl_fp { + d: [ + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, + ], + }, +}); + +pub const G2_GENERATOR: MclG2 = MclG2(mcl_g2 { + x: mcl_fp2 { + d: [ + mcl_fp { + d: [ + 0xf5f28fa202940a10, + 0xb3f5fb2687b4961a, + 0xa1a893b53e2ae580, + 0x9894999d1a3caee9, + 0x6f67b7631863366b, + 0x058191924350bcd7, + ], + }, + mcl_fp { + d: [ + 0xa5a9c0759e23f606, + 0xaaa0c59dbccd60c3, + 0x3bb17e18e2867806, + 0x1b1ab6cc8541b367, + 0xc2b6ed0ef2158547, + 0x11922a097360edf3, + ], + }, + ], + }, + y: mcl_fp2 { + d: [ + mcl_fp { + d: [ + 0x4c730af860494c4a, + 0x597cfa1f5e369c5a, + 0xe7e6856caa0a635a, + 0xbbefb5e96e0d495f, + 0x07d3a975f0ef25a2, + 0x0083fd8e7e80dae5, + ], + }, + mcl_fp { + d: [ + 0xadc0fc92df64b05d, + 0x18aa270a2b1461dc, + 0x86adac6a3be4eba0, + 0x79495c4ec93da33a, + 0xe7175850a43ccaed, + 0x0b2bc2a163de1bf2, + ], + }, + ], + }, + z: mcl_fp2 { + d: [ + mcl_fp { + d: [ + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, + ], + }, + mcl_fp { + d: [ + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + ], + }, + ], + }, +}); + +pub const G2_NEGATIVE_GENERATOR: MclG2 = MclG2(mcl_g2 { + x: mcl_fp2 { + d: [ + mcl_fp { + d: [ + 0xf5f28fa202940a10, + 0xb3f5fb2687b4961a, + 0xa1a893b53e2ae580, + 0x9894999d1a3caee9, + 0x6f67b7631863366b, + 0x058191924350bcd7, + ], + }, + mcl_fp { + d: [ + 0xa5a9c0759e23f606, + 0xaaa0c59dbccd60c3, + 0x3bb17e18e2867806, + 0x1b1ab6cc8541b367, + 0xc2b6ed0ef2158547, + 0x11922a097360edf3, + ], + }, + ], + }, + y: mcl_fp2 { + d: [ + mcl_fp { + d: [ + 0x6d8bf5079fb65e61, + 0xc52f05df531d63a5, + 0x7f4a4d344ca692c9, + 0xa887959b8577c95f, + 0x4347fe40525c8734, + 0x197d145bbaff0bb5, + ], + }, + mcl_fp { + d: [ + 0x0c3e036d209afa4e, + 0x0601d8f4863f9e23, + 0xe0832636bacc0a84, + 0xeb2def362a476f84, + 0x64044f659f0ee1e9, + 0x0ed54f48d5a1caa7, + ], + }, + ], + }, + z: mcl_fp2 { + d: [ + mcl_fp { + d: [ + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, + ], + }, + mcl_fp { + d: [ + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + 0x0000000000000000, + ], + }, + ], + }, +}); + +pub const TRUSTED_SETUP_GENERATOR: [u8; 32usize] = [ + 0xa4, 0x73, 0x31, 0x95, 0x28, 0xc8, 0xb6, 0xea, 0x4d, 0x08, 0xcc, 0x53, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; diff --git a/mcl/src/data_availability_sampling.rs b/mcl/src/data_availability_sampling.rs new file mode 100644 index 000000000..3b252c762 --- /dev/null +++ b/mcl/src/data_availability_sampling.rs @@ -0,0 +1,101 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec::Vec; +use core::cmp::Ordering; + +use kzg::{DASExtension, Fr}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; + +// TODO: explain algo +impl MclFFTSettings { + pub fn das_fft_extension_stride(&self, evens: &mut [MclFr], stride: usize) { + match evens.len().cmp(&2) { + Ordering::Less => { + return; + } + Ordering::Equal => { + let x = evens[0].add(&evens[1]); + let y = evens[0].sub(&evens[1]); + let y_times_root = y.mul(&self.roots_of_unity[stride]); + + evens[0] = x.add(&y_times_root); + evens[1] = x.sub(&y_times_root); + + return; + } + Ordering::Greater => {} + } + + let half: usize = evens.len() / 2; + for i in 0..half { + let tmp1 = evens[i].add(&evens[half + i]); + let tmp2 = evens[i].sub(&evens[half + i]); + evens[half + i] = tmp2.mul(&self.reverse_roots_of_unity[i * 2 * stride]); + + evens[i] = tmp1; + } + + #[cfg(feature = "parallel")] + { + if evens.len() > 32 { + let (lo, hi) = evens.split_at_mut(half); + rayon::join( + || self.das_fft_extension_stride(hi, stride * 2), + || self.das_fft_extension_stride(lo, stride * 2), + ); + } else { + // Recurse + self.das_fft_extension_stride(&mut evens[..half], stride * 2); + self.das_fft_extension_stride(&mut evens[half..], stride * 2); + } + } + + #[cfg(not(feature = "parallel"))] + { + // Recurse + self.das_fft_extension_stride(&mut evens[..half], stride * 2); + self.das_fft_extension_stride(&mut evens[half..], stride * 2); + } + + for i in 0..half { + let x = evens[i]; + let y = evens[half + i]; + let y_times_root: MclFr = y.mul(&self.roots_of_unity[(1 + 2 * i) * stride]); + + evens[i] = x.add(&y_times_root); + evens[half + i] = x.sub(&y_times_root); + } + } +} + +impl DASExtension for MclFFTSettings { + /// Polynomial extension for data availability sampling. Given values of even indices, produce values of odd indices. + /// FFTSettings must hold at least 2 times the roots of provided evens. + /// The resulting odd indices make the right half of the coefficients of the inverse FFT of the combined indices zero. + fn das_fft_extension(&self, evens: &[MclFr]) -> Result, String> { + if evens.is_empty() { + return Err(String::from("A non-zero list ab expected")); + } else if !evens.len().is_power_of_two() { + return Err(String::from("A list with power-of-two length expected")); + } else if evens.len() * 2 > self.max_width { + return Err(String::from( + "Supplied list is longer than the available max width", + )); + } + + // In case more roots are provided with fft_settings, use a larger stride + let stride = self.max_width / (evens.len() * 2); + let mut odds = evens.to_vec(); + self.das_fft_extension_stride(&mut odds, stride); + + // TODO: explain why each odd member is multiplied by euclidean inverse of length + let mut inv_len = MclFr::from_u64(odds.len() as u64); + inv_len = inv_len.eucl_inverse(); + let odds = odds.iter().map(|f| f.mul(&inv_len)).collect(); + + Ok(odds) + } +} diff --git a/mcl/src/eip_4844.rs b/mcl/src/eip_4844.rs new file mode 100644 index 000000000..ff9d4f383 --- /dev/null +++ b/mcl/src/eip_4844.rs @@ -0,0 +1,399 @@ +extern crate alloc; + +use alloc::boxed::Box; +use alloc::vec::Vec; +use core::ptr; +use kzg::eip_4844::{ + blob_to_kzg_commitment_rust, compute_blob_kzg_proof_rust, compute_kzg_proof_rust, + load_trusted_setup_rust, verify_blob_kzg_proof_batch_rust, verify_blob_kzg_proof_rust, + verify_kzg_proof_rust, BYTES_PER_G1, FIELD_ELEMENTS_PER_BLOB, TRUSTED_SETUP_NUM_G1_POINTS, + TRUSTED_SETUP_NUM_G2_POINTS, +}; +use kzg::eth::c_bindings::{ + Blob, Bytes32, Bytes48, CKZGSettings, CKzgRet, KZGCommitment, KZGProof, +}; +use kzg::eth::{FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB}; +use kzg::{cfg_into_iter, Fr, G1}; +#[cfg(feature = "std")] +use libc::FILE; +#[cfg(feature = "std")] +use std::fs::File; +#[cfg(feature = "std")] +use std::io::Read; + +#[cfg(feature = "std")] +use kzg::eip_4844::load_trusted_setup_string; + +use crate::types::fr::MclFr; + +use crate::types::g1::MclG1; +use crate::types::kzg_settings::MclKZGSettings; +use crate::utils::{ + deserialize_blob, handle_ckzg_badargs, kzg_settings_to_c, PRECOMPUTATION_TABLES, +}; + +#[cfg(feature = "parallel")] +use rayon::prelude::*; + +#[cfg(feature = "std")] +pub fn load_trusted_setup_filename_rust( + filepath: &str, +) -> Result { + let mut file = File::open(filepath).map_err(|_| "Unable to open file".to_string())?; + let mut contents = String::new(); + file.read_to_string(&mut contents) + .map_err(|_| "Unable to read file".to_string())?; + + let (g1_monomial_bytes, g1_lagrange_bytes, g2_monomial_bytes) = + load_trusted_setup_string(&contents)?; + load_trusted_setup_rust(&g1_monomial_bytes, &g1_lagrange_bytes, &g2_monomial_bytes) +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn blob_to_kzg_commitment( + out: *mut KZGCommitment, + blob: *const Blob, + s: &CKZGSettings, +) -> CKzgRet { + if TRUSTED_SETUP_NUM_G1_POINTS == 0 { + // FIXME: load_trusted_setup should set this value, but if not, it fails + TRUSTED_SETUP_NUM_G1_POINTS = FIELD_ELEMENTS_PER_BLOB + }; + + let deserialized_blob = handle_ckzg_badargs!(deserialize_blob(blob)); + let settings: MclKZGSettings = handle_ckzg_badargs!(s.try_into()); + let tmp = handle_ckzg_badargs!(blob_to_kzg_commitment_rust(&deserialized_blob, &settings)); + + (*out).bytes = tmp.to_bytes(); + CKzgRet::Ok +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn load_trusted_setup( + out: *mut CKZGSettings, + g1_monomial_bytes: *const u8, + num_g1_monomial_bytes: u64, + g1_lagrange_bytes: *const u8, + num_g1_lagrange_bytes: u64, + g2_monomial_bytes: *const u8, + num_g2_monomial_bytes: u64, + _precompute: u64, +) -> CKzgRet { + *out = CKZGSettings { + brp_roots_of_unity: ptr::null_mut(), + roots_of_unity: ptr::null_mut(), + reverse_roots_of_unity: ptr::null_mut(), + g1_values_monomial: ptr::null_mut(), + g1_values_lagrange_brp: ptr::null_mut(), + g2_values_monomial: ptr::null_mut(), + x_ext_fft_columns: ptr::null_mut(), + tables: ptr::null_mut(), + wbits: 0, + scratch_size: 0, + }; + + let g1_monomial_bytes = + core::slice::from_raw_parts(g1_monomial_bytes, num_g1_monomial_bytes as usize); + let g1_lagrange_bytes = + core::slice::from_raw_parts(g1_lagrange_bytes, num_g1_lagrange_bytes as usize); + let g2_monomial_bytes = + core::slice::from_raw_parts(g2_monomial_bytes, num_g2_monomial_bytes as usize); + TRUSTED_SETUP_NUM_G1_POINTS = num_g1_monomial_bytes as usize / BYTES_PER_G1; + let mut settings = handle_ckzg_badargs!(load_trusted_setup_rust( + g1_monomial_bytes, + g1_lagrange_bytes, + g2_monomial_bytes + )); + + let c_settings = kzg_settings_to_c(&settings); + + PRECOMPUTATION_TABLES.save_precomputation(settings.precomputation.take(), &c_settings); + + *out = c_settings; + CKzgRet::Ok +} + +/// # Safety +#[cfg(feature = "std")] +#[no_mangle] +pub unsafe extern "C" fn load_trusted_setup_file( + out: *mut CKZGSettings, + in_: *mut FILE, +) -> CKzgRet { + *out = CKZGSettings { + brp_roots_of_unity: ptr::null_mut(), + roots_of_unity: ptr::null_mut(), + reverse_roots_of_unity: ptr::null_mut(), + g1_values_monomial: ptr::null_mut(), + g1_values_lagrange_brp: ptr::null_mut(), + g2_values_monomial: ptr::null_mut(), + x_ext_fft_columns: ptr::null_mut(), + tables: ptr::null_mut(), + wbits: 0, + scratch_size: 0, + }; + + let mut buf = vec![0u8; 1024 * 1024]; + let len: usize = libc::fread(buf.as_mut_ptr() as *mut libc::c_void, 1, buf.len(), in_); + let s = handle_ckzg_badargs!(String::from_utf8(buf[..len].to_vec())); + let (g1_monomial_bytes, g1_lagrange_bytes, g2_monomial_bytes) = + handle_ckzg_badargs!(load_trusted_setup_string(&s)); + TRUSTED_SETUP_NUM_G1_POINTS = g1_monomial_bytes.len() / BYTES_PER_G1; + if TRUSTED_SETUP_NUM_G1_POINTS != FIELD_ELEMENTS_PER_BLOB { + // Helps pass the Java test "shouldThrowExceptionOnIncorrectTrustedSetupFromFile", + // as well as 5 others that pass only if this one passes (likely because Java doesn't + // deallocate its KZGSettings pointer when no exception is thrown). + return CKzgRet::BadArgs; + } + let mut settings = handle_ckzg_badargs!(load_trusted_setup_rust( + &g1_monomial_bytes, + &g1_lagrange_bytes, + &g2_monomial_bytes + )); + + let c_settings = kzg_settings_to_c(&settings); + + PRECOMPUTATION_TABLES.save_precomputation(settings.precomputation.take(), &c_settings); + + *out = c_settings; + + CKzgRet::Ok +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn compute_blob_kzg_proof( + out: *mut KZGProof, + blob: *const Blob, + commitment_bytes: *const Bytes48, + s: &CKZGSettings, +) -> CKzgRet { + let deserialized_blob = match deserialize_blob(blob) { + Ok(value) => value, + Err(err) => return err, + }; + + let commitment_g1 = handle_ckzg_badargs!(MclG1::from_bytes(&(*commitment_bytes).bytes)); + let settings: MclKZGSettings = handle_ckzg_badargs!(s.try_into()); + let proof = handle_ckzg_badargs!(compute_blob_kzg_proof_rust( + &deserialized_blob, + &commitment_g1, + &settings + )); + + (*out).bytes = proof.to_bytes(); + CKzgRet::Ok +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn free_trusted_setup(s: *mut CKZGSettings) { + if s.is_null() { + return; + } + + PRECOMPUTATION_TABLES.remove_precomputation(&*s); + + if !(*s).g1_values_monomial.is_null() { + let v = Box::from_raw(core::slice::from_raw_parts_mut( + (*s).g1_values_monomial, + FIELD_ELEMENTS_PER_BLOB, + )); + drop(v); + (*s).g1_values_monomial = ptr::null_mut(); + } + + if !(*s).g1_values_lagrange_brp.is_null() { + let v = Box::from_raw(core::slice::from_raw_parts_mut( + (*s).g1_values_lagrange_brp, + FIELD_ELEMENTS_PER_BLOB, + )); + drop(v); + (*s).g1_values_lagrange_brp = ptr::null_mut(); + } + + if !(*s).g2_values_monomial.is_null() { + let v = Box::from_raw(core::slice::from_raw_parts_mut( + (*s).g2_values_monomial, + TRUSTED_SETUP_NUM_G2_POINTS, + )); + drop(v); + (*s).g2_values_monomial = ptr::null_mut(); + } + + if !(*s).x_ext_fft_columns.is_null() { + let v = Box::from_raw(core::slice::from_raw_parts_mut( + (*s).x_ext_fft_columns, + 2 * ((FIELD_ELEMENTS_PER_EXT_BLOB / 2) / FIELD_ELEMENTS_PER_CELL), + )); + drop(v); + (*s).x_ext_fft_columns = ptr::null_mut(); + } + + if !(*s).roots_of_unity.is_null() { + let v = Box::from_raw(core::slice::from_raw_parts_mut( + (*s).roots_of_unity, + FIELD_ELEMENTS_PER_EXT_BLOB + 1, + )); + drop(v); + (*s).roots_of_unity = ptr::null_mut(); + } + + if !(*s).reverse_roots_of_unity.is_null() { + let v = Box::from_raw(core::slice::from_raw_parts_mut( + (*s).reverse_roots_of_unity, + FIELD_ELEMENTS_PER_EXT_BLOB + 1, + )); + drop(v); + (*s).reverse_roots_of_unity = ptr::null_mut(); + } + + if !(*s).brp_roots_of_unity.is_null() { + let v = Box::from_raw(core::slice::from_raw_parts_mut( + (*s).brp_roots_of_unity, + FIELD_ELEMENTS_PER_EXT_BLOB, + )); + drop(v); + (*s).brp_roots_of_unity = ptr::null_mut(); + } +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn verify_kzg_proof( + ok: *mut bool, + commitment_bytes: *const Bytes48, + z_bytes: *const Bytes32, + y_bytes: *const Bytes32, + proof_bytes: *const Bytes48, + s: &CKZGSettings, +) -> CKzgRet { + let frz = handle_ckzg_badargs!(MclFr::from_bytes(&(*z_bytes).bytes)); + let fry = handle_ckzg_badargs!(MclFr::from_bytes(&(*y_bytes).bytes)); + let g1commitment = handle_ckzg_badargs!(MclG1::from_bytes(&(*commitment_bytes).bytes)); + let g1proof = handle_ckzg_badargs!(MclG1::from_bytes(&(*proof_bytes).bytes)); + + let settings: MclKZGSettings = handle_ckzg_badargs!(s.try_into()); + + let result = handle_ckzg_badargs!(verify_kzg_proof_rust( + &g1commitment, + &frz, + &fry, + &g1proof, + &settings + )); + + *ok = result; + CKzgRet::Ok +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn verify_blob_kzg_proof( + ok: *mut bool, + blob: *const Blob, + commitment_bytes: *const Bytes48, + proof_bytes: *const Bytes48, + s: &CKZGSettings, +) -> CKzgRet { + let deserialized_blob = handle_ckzg_badargs!(deserialize_blob(blob)); + let commitment_g1 = handle_ckzg_badargs!(MclG1::from_bytes(&(*commitment_bytes).bytes)); + let proof_g1 = handle_ckzg_badargs!(MclG1::from_bytes(&(*proof_bytes).bytes)); + let settings: MclKZGSettings = handle_ckzg_badargs!(s.try_into()); + + let result = handle_ckzg_badargs!(verify_blob_kzg_proof_rust( + &deserialized_blob, + &commitment_g1, + &proof_g1, + &settings, + )); + + *ok = result; + CKzgRet::Ok +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn verify_blob_kzg_proof_batch( + ok: *mut bool, + blobs: *const Blob, + commitments_bytes: *const Bytes48, + proofs_bytes: *const Bytes48, + n: usize, + s: &CKZGSettings, +) -> CKzgRet { + let raw_blobs = core::slice::from_raw_parts(blobs, n); + let raw_commitments = core::slice::from_raw_parts(commitments_bytes, n); + let raw_proofs = core::slice::from_raw_parts(proofs_bytes, n); + + let deserialized_blobs: Result>, CKzgRet> = cfg_into_iter!(raw_blobs) + .map(|raw_blob| deserialize_blob(raw_blob).map_err(|_| CKzgRet::BadArgs)) + .collect(); + + let commitments_g1: Result, CKzgRet> = cfg_into_iter!(raw_commitments) + .map(|raw_commitment| MclG1::from_bytes(&raw_commitment.bytes).map_err(|_| CKzgRet::BadArgs)) + .collect(); + + let proofs_g1: Result, CKzgRet> = cfg_into_iter!(raw_proofs) + .map(|raw_proof| MclG1::from_bytes(&raw_proof.bytes).map_err(|_| CKzgRet::BadArgs)) + .collect(); + + if let (Ok(blobs), Ok(commitments), Ok(proofs)) = + (deserialized_blobs, commitments_g1, proofs_g1) + { + let settings: MclKZGSettings = match s.try_into() { + Ok(value) => value, + Err(_) => return CKzgRet::BadArgs, + }; + + let result = + verify_blob_kzg_proof_batch_rust(blobs.as_slice(), &commitments, &proofs, &settings); + + if let Ok(result) = result { + *ok = result; + CKzgRet::Ok + } else { + CKzgRet::BadArgs + } + } else { + *ok = false; + CKzgRet::BadArgs + } +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn compute_kzg_proof( + proof_out: *mut KZGProof, + y_out: *mut Bytes32, + blob: *const Blob, + z_bytes: *const Bytes32, + s: &CKZGSettings, +) -> CKzgRet { + let deserialized_blob = match deserialize_blob(blob) { + Ok(value) => value, + Err(err) => return err, + }; + + let frz = match MclFr::from_bytes(&(*z_bytes).bytes) { + Ok(value) => value, + Err(_) => return CKzgRet::BadArgs, + }; + + let settings: MclKZGSettings = match s.try_into() { + Ok(value) => value, + Err(_) => return CKzgRet::BadArgs, + }; + + let (proof_out_tmp, fry_tmp) = match compute_kzg_proof_rust(&deserialized_blob, &frz, &settings) + { + Ok(value) => value, + Err(_) => return CKzgRet::BadArgs, + }; + + (*proof_out).bytes = proof_out_tmp.to_bytes(); + (*y_out).bytes = fry_tmp.to_bytes(); + CKzgRet::Ok +} diff --git a/mcl/src/eip_7594.rs b/mcl/src/eip_7594.rs new file mode 100644 index 000000000..92c867b3e --- /dev/null +++ b/mcl/src/eip_7594.rs @@ -0,0 +1,29 @@ +extern crate alloc; + +use kzg::EcBackend; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fp::MclFp; +use crate::types::g1::MclG1; +use crate::types::g1::FsG1Affine; +use crate::types::g2::MclG2; +use crate::types::kzg_settings::MclKZGSettings; +use crate::types::poly::MclPoly; +use kzg::c_bindings_eip7594; + +use crate::types::fr::MclFr; + +pub struct MclBackend; + +impl EcBackend for MclBackend { + type Fr = MclFr; + type G1Fp = MclFp; + type G1Affine = FsG1Affine; + type G1 = MclG1; + type G2 = MclG2; + type Poly = MclPoly; + type FFTSettings = MclFFTSettings; + type KZGSettings = MclKZGSettings; +} + +c_bindings_eip7594!(MclBackend); diff --git a/mcl/src/fft_fr.rs b/mcl/src/fft_fr.rs new file mode 100644 index 000000000..2a1e43a0e --- /dev/null +++ b/mcl/src/fft_fr.rs @@ -0,0 +1,145 @@ +extern crate alloc; + +use alloc::format; +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; + +use kzg::{FFTFr, Fr}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; + +/// Fast Fourier Transform for finite field elements. Polynomial ret is operated on in reverse order: ret_i * x ^ (len - i - 1) +pub fn fft_fr_fast( + ret: &mut [MclFr], + data: &[MclFr], + stride: usize, + roots: &[MclFr], + roots_stride: usize, +) { + let half: usize = ret.len() / 2; + if half > 0 { + // Recurse + // Offsetting data by stride = 1 on the first iteration forces the even members to the first half + // and the odd members to the second half + #[cfg(not(feature = "parallel"))] + { + fft_fr_fast(&mut ret[..half], data, stride * 2, roots, roots_stride * 2); + fft_fr_fast( + &mut ret[half..], + &data[stride..], + stride * 2, + roots, + roots_stride * 2, + ); + } + + #[cfg(feature = "parallel")] + { + if half > 256 { + let (lo, hi) = ret.split_at_mut(half); + rayon::join( + || fft_fr_fast(lo, data, stride * 2, roots, roots_stride * 2), + || fft_fr_fast(hi, &data[stride..], stride * 2, roots, roots_stride * 2), + ); + } else { + fft_fr_fast(&mut ret[..half], data, stride * 2, roots, roots_stride * 2); + fft_fr_fast( + &mut ret[half..], + &data[stride..], + stride * 2, + roots, + roots_stride * 2, + ); + } + } + + for i in 0..half { + let y_times_root = ret[i + half].mul(&roots[i * roots_stride]); + ret[i + half] = ret[i].sub(&y_times_root); + ret[i] = ret[i].add(&y_times_root); + } + } else { + // When len = 1, return the permuted element + ret[0] = data[0]; + } +} + +impl MclFFTSettings { + /// Fast Fourier Transform for finite field elements, `output` must be zeroes + pub(crate) fn fft_fr_output( + &self, + data: &[MclFr], + inverse: bool, + output: &mut [MclFr], + ) -> Result<(), String> { + if data.len() > self.max_width { + return Err(String::from( + "Supplied list is longer than the available max width", + )); + } + if data.len() != output.len() { + return Err(format!( + "Output length {} doesn't match data length {}", + data.len(), + output.len() + )); + } + if !data.len().is_power_of_two() { + return Err(String::from("A list with power-of-two length expected")); + } + + // In case more roots are provided with fft_settings, use a larger stride + let stride = self.max_width / data.len(); + + // Inverse is same as regular, but all constants are reversed and results are divided by n + // This is a property of the DFT matrix + let roots = if inverse { + &self.reverse_roots_of_unity + } else { + &self.roots_of_unity + }; + + fft_fr_fast(output, data, 1, roots, stride); + + if inverse { + let inv_fr_len = MclFr::from_u64(data.len() as u64).inverse(); + output.iter_mut().for_each(|f| *f = f.mul(&inv_fr_len)); + } + + Ok(()) + } +} + +impl FFTFr for MclFFTSettings { + /// Fast Fourier Transform for finite field elements + fn fft_fr(&self, data: &[MclFr], inverse: bool) -> Result, String> { + let mut ret = vec![MclFr::default(); data.len()]; + + self.fft_fr_output(data, inverse, &mut ret)?; + + Ok(ret) + } +} + +/// Simplified Discrete Fourier Transform, mainly used for testing +pub fn fft_fr_slow( + ret: &mut [MclFr], + data: &[MclFr], + stride: usize, + roots: &[MclFr], + roots_stride: usize, +) { + for i in 0..data.len() { + // Evaluate first member at 1 + ret[i] = data[0].mul(&roots[0]); + + // Evaluate the rest of members using a step of (i * J) % data.len() over the roots + // This distributes the roots over correct x^n members and saves on multiplication + for j in 1..data.len() { + let v = data[j * stride].mul(&roots[((i * j) % data.len()) * roots_stride]); + ret[i] = ret[i].add(&v); + } + } +} diff --git a/mcl/src/fft_g1.rs b/mcl/src/fft_g1.rs new file mode 100644 index 000000000..3eabe5d8e --- /dev/null +++ b/mcl/src/fft_g1.rs @@ -0,0 +1,104 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; + +use kzg::{Fr, G1Mul, FFTG1, G1}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; +use crate::types::g1::MclG1; + +pub fn fft_g1_fast( + ret: &mut [MclG1], + data: &[MclG1], + stride: usize, + roots: &[MclFr], + roots_stride: usize, +) { + let half = ret.len() / 2; + if half > 0 { + #[cfg(feature = "parallel")] + { + let (lo, hi) = ret.split_at_mut(half); + rayon::join( + || fft_g1_fast(lo, data, stride * 2, roots, roots_stride * 2), + || fft_g1_fast(hi, &data[stride..], stride * 2, roots, roots_stride * 2), + ); + } + + #[cfg(not(feature = "parallel"))] + { + fft_g1_fast(&mut ret[..half], data, stride * 2, roots, roots_stride * 2); + fft_g1_fast( + &mut ret[half..], + &data[stride..], + stride * 2, + roots, + roots_stride * 2, + ); + } + + for i in 0..half { + let y_times_root = ret[i + half].mul(&roots[i * roots_stride]); + ret[i + half] = ret[i].sub(&y_times_root); + ret[i] = ret[i].add_or_dbl(&y_times_root); + } + } else { + ret[0] = data[0]; + } +} + +impl FFTG1 for MclFFTSettings { + fn fft_g1(&self, data: &[MclG1], inverse: bool) -> Result, String> { + if data.len() > self.max_width { + return Err(String::from( + "Supplied list is longer than the available max width", + )); + } else if !data.len().is_power_of_two() { + return Err(String::from("A list with power-of-two length expected")); + } + + let stride = self.max_width / data.len(); + let mut ret = vec![MclG1::default(); data.len()]; + + let roots = if inverse { + &self.reverse_roots_of_unity + } else { + &self.roots_of_unity + }; + + fft_g1_fast(&mut ret, data, 1, roots, stride); + + if inverse { + let inv_fr_len = MclFr::from_u64(data.len() as u64).inverse(); + ret[..data.len()] + .iter_mut() + .for_each(|f| *f = f.mul(&inv_fr_len)); + } + + Ok(ret) + } +} + +// Used for testing +pub fn fft_g1_slow( + ret: &mut [MclG1], + data: &[MclG1], + stride: usize, + roots: &[MclFr], + roots_stride: usize, +) { + for i in 0..data.len() { + // Evaluate first member at 1 + ret[i] = data[0].mul(&roots[0]); + + // Evaluate the rest of members using a step of (i * J) % data.len() over the roots + // This distributes the roots over correct x^n members and saves on multiplication + for j in 1..data.len() { + let v = data[j * stride].mul(&roots[((i * j) % data.len()) * roots_stride]); + ret[i] = ret[i].add_or_dbl(&v); + } + } +} diff --git a/mcl/src/fk20_proofs.rs b/mcl/src/fk20_proofs.rs new file mode 100644 index 000000000..95bf5b75c --- /dev/null +++ b/mcl/src/fk20_proofs.rs @@ -0,0 +1,93 @@ +extern crate alloc; + +use alloc::vec; +use alloc::vec::Vec; + +use kzg::{FFTFr, Fr, G1Mul, Poly, FFTG1, G1}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; +use crate::types::g1::MclG1; +use crate::types::poly::MclPoly; + +#[cfg(feature = "parallel")] +use rayon::prelude::*; + +impl MclFFTSettings { + pub fn toeplitz_part_1(&self, x: &[MclG1]) -> Vec { + let n = x.len(); + let n2 = n * 2; + let mut x_ext = Vec::with_capacity(n2); + + x_ext.extend(x.iter().take(n)); + x_ext.resize(n2, MclG1::identity()); + + self.fft_g1(&x_ext, false).unwrap() + } + + /// poly and x_ext_fft should be of same length + pub fn toeplitz_part_2(&self, poly: &MclPoly, x_ext_fft: &[MclG1]) -> Vec { + let coeffs_fft = self.fft_fr(&poly.coeffs, false).unwrap(); + + #[cfg(feature = "parallel")] + { + coeffs_fft + .into_par_iter() + .zip(x_ext_fft) + .take(poly.len()) + .map(|(coeff_fft, x_ext_fft)| x_ext_fft.mul(&coeff_fft)) + .collect() + } + + #[cfg(not(feature = "parallel"))] + { + coeffs_fft + .into_iter() + .zip(x_ext_fft) + .take(poly.len()) + .map(|(coeff_fft, x_ext_fft)| x_ext_fft.mul(&coeff_fft)) + .collect() + } + } + + pub fn toeplitz_part_3(&self, h_ext_fft: &[MclG1]) -> Vec { + let n2 = h_ext_fft.len(); + let n = n2 / 2; + + let mut ret = self.fft_g1(h_ext_fft, true).unwrap(); + ret[n..n2].copy_from_slice(&vec![MclG1::identity(); n2 - n]); + + ret + } +} + +impl MclPoly { + pub fn toeplitz_coeffs_stride(&self, offset: usize, stride: usize) -> MclPoly { + let n = self.len(); + let k = n / stride; + let k2 = k * 2; + + let mut ret = MclPoly::default(); + ret.coeffs.push(self.coeffs[n - 1 - offset]); + + let num_of_zeroes = if k + 2 < k2 { k + 2 - 1 } else { k2 - 1 }; + for _ in 0..num_of_zeroes { + ret.coeffs.push(MclFr::zero()); + } + + let mut i = k + 2; + let mut j = 2 * stride - offset - 1; + while i < k2 { + ret.coeffs.push(self.coeffs[j]); + + i += 1; + j += stride; + } + + ret + } + + pub fn toeplitz_coeffs_step(&self) -> MclPoly { + self.toeplitz_coeffs_stride(0, 1) + } +} diff --git a/mcl/src/kzg_proofs.rs b/mcl/src/kzg_proofs.rs new file mode 100644 index 000000000..fd5d262a5 --- /dev/null +++ b/mcl/src/kzg_proofs.rs @@ -0,0 +1,46 @@ +extern crate alloc; + +use crate::mcl_methods::{mcl_gt, pairing}; +use crate::types::fp::MclFp; +use crate::types::g1::MclG1; +use crate::types::{fr::MclFr, g1::FsG1Affine}; + +use crate::types::g1::MclG1ProjAddAffine; + +use kzg::msm::{msm_impls::msm, precompute::PrecomputationTable}; + +use crate::types::g2::MclG2; + +use kzg::PairingVerify; + +impl PairingVerify for MclG1 { + fn verify(a1: &MclG1, a2: &MclG2, b1: &MclG1, b2: &MclG2) -> bool { + pairings_verify(a1, a2, b1, b2) + } +} + +pub fn g1_linear_combination( + out: &mut MclG1, + points: &[MclG1], + scalars: &[MclFr], + len: usize, + precomputation: Option<&PrecomputationTable>, +) { + *out = msm::( + points, + scalars, + len, + precomputation, + ); +} + +pub fn pairings_verify(a1: &MclG1, a2: &MclG2, b1: &MclG1, b2: &MclG2) -> bool { + // Todo: make optimization + let mut gt0 = mcl_gt::default(); + pairing(&mut gt0, &a1.0, &a2.0); + + let mut gt1 = mcl_gt::default(); + pairing(&mut gt1, &b1.0, &b2.0); + + gt0 == gt1 +} diff --git a/mcl/src/lib.rs b/mcl/src/lib.rs new file mode 100644 index 000000000..12b1406c5 --- /dev/null +++ b/mcl/src/lib.rs @@ -0,0 +1,15 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +pub mod consts; +pub mod data_availability_sampling; +pub mod eip_4844; +pub mod eip_7594; +pub mod fft_fr; +pub mod fft_g1; +pub mod fk20_proofs; +pub mod kzg_proofs; +pub mod recovery; +pub mod types; +pub mod utils; +pub mod zero_poly; +pub mod mcl_methods; \ No newline at end of file diff --git a/mcl/src/mcl_methods.rs b/mcl/src/mcl_methods.rs new file mode 100644 index 000000000..b1a0a2631 --- /dev/null +++ b/mcl/src/mcl_methods.rs @@ -0,0 +1,682 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec::Vec; +use once_cell::sync::OnceCell; +use core::mem::MaybeUninit; +use core::ops::{Add, AddAssign}; +use core::ops::{Div, DivAssign}; +use core::ops::{Mul, MulAssign}; +use core::ops::{Sub, SubAssign}; +use core::primitive::str; + +#[link(name = "mcl", kind = "static")] +#[link(name = "mclbn384_256", kind = "static")] +#[cfg_attr(target_arch = "x86_64", link(name = "stdc++"))] +#[allow(non_snake_case)] +extern "C" { + // global functions + fn mclBn_init(curve: i32, compiledTimeVar: i32) -> i32; + fn mclBn_getVersion() -> u32; + fn mclBn_getFrByteSize() -> u32; + fn mclBn_getFpByteSize() -> u32; + fn mclBn_getCurveOrder(buf: *mut u8, maxBufSize: usize) -> usize; + fn mclBn_getFieldOrder(buf: *mut u8, maxBufSize: usize) -> usize; + fn mclBn_pairing(z: *mut mcl_gt, x: *const mcl_g1, y: *const mcl_g2); + fn mclBn_millerLoop(z: *mut mcl_gt, x: *const mcl_g1, y: *const mcl_g2); + fn mclBn_finalExp(y: *mut mcl_gt, x: *const mcl_gt); + + // mcl_fr + fn mclBnFr_isEqual(x: *const mcl_fr, y: *const mcl_fr) -> i32; + fn mclBnFr_isValid(x: *const mcl_fr) -> i32; + fn mclBnFr_isZero(x: *const mcl_fr) -> i32; + fn mclBnFr_isOne(x: *const mcl_fr) -> i32; + fn mclBnFr_isOdd(x: *const mcl_fr) -> i32; + fn mclBnFr_isNegative(x: *const mcl_fr) -> i32; + fn mclBnFr_cmp(x: *const mcl_fr, y: *const mcl_fr) -> i32; + + fn mclBnFr_setStr(x: *mut mcl_fr, buf: *const u8, bufSize: usize, ioMode: i32) -> i32; + fn mclBnFr_getStr(buf: *mut u8, maxBufSize: usize, x: *const mcl_fr, ioMode: i32) -> usize; + fn mclBnFr_serialize(buf: *mut u8, maxBufSize: usize, x: *const mcl_fr) -> usize; + fn mclBnFr_deserialize(x: *mut mcl_fr, buf: *const u8, bufSize: usize) -> usize; + + fn mclBnFr_setInt32(x: *mut mcl_fr, v: i32); + fn mclBnFr_setLittleEndian(x: *mut mcl_fr, buf: *const u8, bufSize: usize) -> i32; + fn mclBnFr_setLittleEndianMod(x: *mut mcl_fr, buf: *const u8, bufSize: usize) -> i32; + fn mclBnFr_setHashOf(x: *mut mcl_fr, buf: *const u8, bufSize: usize) -> i32; + fn mclBnFr_setByCSPRNG(x: *mut mcl_fr); + + fn mclBnFr_add(z: *mut mcl_fr, x: *const mcl_fr, y: *const mcl_fr); + fn mclBnFr_sub(z: *mut mcl_fr, x: *const mcl_fr, y: *const mcl_fr); + fn mclBnFr_neg(y: *mut mcl_fr, x: *const mcl_fr); + + fn mclBnFr_mul(z: *mut mcl_fr, x: *const mcl_fr, y: *const mcl_fr); + fn mclBnFr_div(z: *mut mcl_fr, x: *const mcl_fr, y: *const mcl_fr); + fn mclBnFr_inv(y: *mut mcl_fr, x: *const mcl_fr); + fn mclBnFr_sqr(y: *mut mcl_fr, x: *const mcl_fr); + fn mclBnFr_squareRoot(y: *mut mcl_fr, x: *const mcl_fr) -> i32; + + // mcl_fp + pub fn mclBnFp_isEqual(x: *const mcl_fp, y: *const mcl_fp) -> i32; + pub fn mclBnFp_isValid(x: *const mcl_fp) -> i32; + pub fn mclBnFp_isZero(x: *const mcl_fp) -> i32; + pub fn mclBnFp_isOne(x: *const mcl_fp) -> i32; + pub fn mclBnFp_isOdd(x: *const mcl_fp) -> i32; + pub fn mclBnFp_isNegative(x: *const mcl_fp) -> i32; + pub fn mclBnFp_cmp(x: *const mcl_fp, y: *const mcl_fp) -> i32; + + pub fn mclBnFp_setStr(x: *mut mcl_fp, buf: *const u8, bufSize: usize, ioMode: i32) -> i32; + pub fn mclBnFp_getStr(buf: *mut u8, maxBufSize: usize, x: *const mcl_fp, ioMode: i32) -> usize; + pub fn mclBnFp_serialize(buf: *mut u8, maxBufSize: usize, x: *const mcl_fp) -> usize; + pub fn mclBnFp_deserialize(x: *mut mcl_fp, buf: *const u8, bufSize: usize) -> usize; + + pub fn mclBnFp_setInt32(x: *mut mcl_fp, v: i32); + pub fn mclBnFp_setLittleEndian(x: *mut mcl_fp, buf: *const u8, bufSize: usize) -> i32; + pub fn mclBnFp_setLittleEndianMod(x: *mut mcl_fp, buf: *const u8, bufSize: usize) -> i32; + pub fn mclBnFp_setHashOf(x: *mut mcl_fp, buf: *const u8, bufSize: usize) -> i32; + pub fn mclBnFp_setByCSPRNG(x: *mut mcl_fp); + + pub fn mclBnFp_add(z: *mut mcl_fp, x: *const mcl_fp, y: *const mcl_fp); + pub fn mclBnFp_sub(z: *mut mcl_fp, x: *const mcl_fp, y: *const mcl_fp); + pub fn mclBnFp_neg(y: *mut mcl_fp, x: *const mcl_fp); + + pub fn mclBnFp_mul(z: *mut mcl_fp, x: *const mcl_fp, y: *const mcl_fp); + pub fn mclBnFp_div(z: *mut mcl_fp, x: *const mcl_fp, y: *const mcl_fp); + pub fn mclBnFp_inv(y: *mut mcl_fp, x: *const mcl_fp); + pub fn mclBnFp_sqr(y: *mut mcl_fp, x: *const mcl_fp); + pub fn mclBnFp_squareRoot(y: *mut mcl_fp, x: *const mcl_fp) -> i32; + + // mcl_fp2 + fn mclBnFp2_isEqual(x: *const mcl_fp2, y: *const mcl_fp2) -> i32; + fn mclBnFp2_isZero(x: *const mcl_fp2) -> i32; + + fn mclBnFp2_serialize(buf: *mut u8, maxBufSize: usize, x: *const mcl_fp2) -> usize; + fn mclBnFp2_deserialize(x: *mut mcl_fp2, buf: *const u8, bufSize: usize) -> usize; + + fn mclBnFp2_add(z: *mut mcl_fp2, x: *const mcl_fp2, y: *const mcl_fp2); + fn mclBnFp2_sub(z: *mut mcl_fp2, x: *const mcl_fp2, y: *const mcl_fp2); + fn mclBnFp2_neg(y: *mut mcl_fp2, x: *const mcl_fp2); + + fn mclBnFp2_mul(z: *mut mcl_fp2, x: *const mcl_fp2, y: *const mcl_fp2); + fn mclBnFp2_div(z: *mut mcl_fp2, x: *const mcl_fp2, y: *const mcl_fp2); + fn mclBnFp2_inv(y: *mut mcl_fp2, x: *const mcl_fp2); + fn mclBnFp2_sqr(y: *mut mcl_fp2, x: *const mcl_fp2); + fn mclBnFp2_squareRoot(y: *mut mcl_fp2, x: *const mcl_fp2) -> i32; + + // mcl_g1 + fn mclBnG1_isEqual(x: *const mcl_g1, y: *const mcl_g1) -> i32; + fn mclBnG1_isValid(x: *const mcl_g1) -> i32; + fn mclBnG1_isZero(x: *const mcl_g1) -> i32; + + fn mclBnG1_setStr(x: *mut mcl_g1, buf: *const u8, bufSize: usize, ioMode: i32) -> i32; + fn mclBnG1_getStr(buf: *mut u8, maxBufSize: usize, x: *const mcl_g1, ioMode: i32) -> usize; + fn mclBnG1_serialize(buf: *mut u8, maxBufSize: usize, x: *const mcl_g1) -> usize; + fn mclBnG1_deserialize(x: *mut mcl_g1, buf: *const u8, bufSize: usize) -> usize; + + fn mclBnG1_add(z: *mut mcl_g1, x: *const mcl_g1, y: *const mcl_g1); + fn mclBnG1_sub(z: *mut mcl_g1, x: *const mcl_g1, y: *const mcl_g1); + fn mclBnG1_neg(y: *mut mcl_g1, x: *const mcl_g1); + + fn mclBnG1_dbl(y: *mut mcl_g1, x: *const mcl_g1); + fn mclBnG1_mul(z: *mut mcl_g1, x: *const mcl_g1, y: *const mcl_fr); + fn mclBnG1_normalize(y: *mut mcl_g1, x: *const mcl_g1); + fn mclBnG1_hashAndMapTo(x: *mut mcl_g1, buf: *const u8, bufSize: usize) -> i32; + fn mclBnG1_mulVec(z: *mut mcl_g1, x: *const mcl_g1, y: *const mcl_fr, n: usize); + + // mcl_g2 + fn mclBnG2_isEqual(x: *const mcl_g2, y: *const mcl_g2) -> i32; + fn mclBnG2_isValid(x: *const mcl_g2) -> i32; + fn mclBnG2_isZero(x: *const mcl_g2) -> i32; + + fn mclBnG2_setStr(x: *mut mcl_g2, buf: *const u8, bufSize: usize, ioMode: i32) -> i32; + fn mclBnG2_getStr(buf: *mut u8, maxBufSize: usize, x: *const mcl_g2, ioMode: i32) -> usize; + fn mclBnG2_serialize(buf: *mut u8, maxBufSize: usize, x: *const mcl_g2) -> usize; + fn mclBnG2_deserialize(x: *mut mcl_g2, buf: *const u8, bufSize: usize) -> usize; + + fn mclBnG2_add(z: *mut mcl_g2, x: *const mcl_g2, y: *const mcl_g2); + fn mclBnG2_sub(z: *mut mcl_g2, x: *const mcl_g2, y: *const mcl_g2); + fn mclBnG2_neg(y: *mut mcl_g2, x: *const mcl_g2); + + fn mclBnG2_dbl(y: *mut mcl_g2, x: *const mcl_g2); + fn mclBnG2_mul(z: *mut mcl_g2, x: *const mcl_g2, y: *const mcl_fr); + fn mclBnG2_normalize(y: *mut mcl_g2, x: *const mcl_g2); + fn mclBnG2_hashAndMapTo(x: *mut mcl_g2, buf: *const u8, bufSize: usize) -> i32; + fn mclBnG2_mulVec(z: *mut mcl_g2, x: *const mcl_g2, y: *const mcl_fr, n: usize); + + // mcl_gt + fn mclBnGT_isEqual(x: *const mcl_gt, y: *const mcl_gt) -> i32; + fn mclBnGT_isZero(x: *const mcl_gt) -> i32; + fn mclBnGT_isOne(x: *const mcl_gt) -> i32; + + fn mclBnGT_setStr(x: *mut mcl_gt, buf: *const u8, bufSize: usize, ioMode: i32) -> i32; + fn mclBnGT_getStr(buf: *mut u8, maxBufSize: usize, x: *const mcl_gt, ioMode: i32) -> usize; + fn mclBnGT_serialize(buf: *mut u8, maxBufSize: usize, x: *const mcl_gt) -> usize; + fn mclBnGT_deserialize(x: *mut mcl_gt, buf: *const u8, bufSize: usize) -> usize; + + fn mclBnGT_setInt32(x: *mut mcl_gt, v: i32); + + fn mclBnGT_add(z: *mut mcl_gt, x: *const mcl_gt, y: *const mcl_gt); + fn mclBnGT_sub(z: *mut mcl_gt, x: *const mcl_gt, y: *const mcl_gt); + fn mclBnGT_neg(y: *mut mcl_gt, x: *const mcl_gt); + + fn mclBnGT_mul(z: *mut mcl_gt, x: *const mcl_gt, y: *const mcl_gt); + fn mclBnGT_div(z: *mut mcl_gt, x: *const mcl_gt, y: *const mcl_gt); + fn mclBnGT_inv(y: *mut mcl_gt, x: *const mcl_gt); + fn mclBnGT_sqr(y: *mut mcl_gt, x: *const mcl_gt); + + fn mclBnGT_pow(z: *mut mcl_gt, x: *const mcl_gt, y: *const mcl_fr); +} + +pub enum CurveType { + BN254 = 0, + BN381 = 1, + SNARK = 4, + BLS12_381 = 5, + BLS12_377 = 8, + #[allow(non_camel_case_types)] + BN_P256 = 9, +} + +const MCLBN_FP_UNIT_SIZE: usize = 6; +const MCLBN_FR_UNIT_SIZE: usize = 4; +const MCLBN_COMPILED_TIME_VAR: i32 = MCLBN_FR_UNIT_SIZE as i32 * 10 + MCLBN_FP_UNIT_SIZE as i32; + +macro_rules! common_impl { + ($t:ty, $is_equal_fn:ident, $is_zero_fn:ident) => { + impl PartialEq for $t { + fn eq(&self, rhs: &Self) -> bool { + unsafe { $is_equal_fn(self, rhs) == 1 } + } + } + impl $t { + pub fn zero() -> $t { + Default::default() + } + pub unsafe fn uninit() -> $t { + let u = MaybeUninit::<$t>::uninit(); + let v = unsafe { u.assume_init() }; + v + } + pub fn clear(&mut self) { + *self = <$t>::zero() + } + pub fn is_zero(&self) -> bool { + unsafe { $is_zero_fn(self) == 1 } + } + } + }; +} +macro_rules! is_valid_impl { + ($t:ty, $is_valid_fn:ident) => { + impl $t { + pub fn is_valid(&self) -> bool { + unsafe { $is_valid_fn(self) == 1 } + } + } + }; +} + +macro_rules! serialize_impl { + ($t:ty, $size:expr, $serialize_fn:ident, $deserialize_fn:ident) => { + impl $t { + pub fn deserialize(&mut self, buf: &[u8]) -> bool { + unsafe { $deserialize_fn(self, buf.as_ptr(), buf.len()) > 0 } + } + pub fn serialize(&self) -> Vec { + let size = unsafe { $size } as usize; + let mut buf: Vec = Vec::with_capacity(size); + let n: usize; + unsafe { + n = $serialize_fn(buf.as_mut_ptr(), size, self); + } + if n == 0 { + panic!("serialize"); + } + unsafe { + buf.set_len(n); + } + buf + } + } + }; +} + +macro_rules! str_impl { + ($t:ty, $maxBufSize:expr, $get_str_fn:ident, $set_str_fn:ident) => { + impl $t { + pub fn from_str(s: &str, base: i32) -> Option<$t> { + let mut v = unsafe { <$t>::uninit() }; + if v.set_str(s, base) { + return Some(v); + } + None + } + pub fn set_str(&mut self, s: &str, base: i32) -> bool { + unsafe { $set_str_fn(self, s.as_ptr(), s.len(), base) == 0 } + } + pub fn get_str(&self, io_mode: i32) -> String { + let u = MaybeUninit::<[u8; $maxBufSize]>::uninit(); + let mut buf = unsafe { u.assume_init() }; + let n: usize; + unsafe { + n = $get_str_fn(buf.as_mut_ptr(), buf.len(), self, io_mode); + } + if n == 0 { + panic!("mclBnFr_getStr"); + } + unsafe { core::str::from_utf8_unchecked(&buf[0..n]).into() } + } + } + }; +} + +macro_rules! int_impl { + ($t:ty, $set_int_fn:ident, $is_one_fn:ident) => { + impl $t { + pub fn from_int(x: i32) -> $t { + let mut v = unsafe { <$t>::uninit() }; + v.set_int(x); + v + } + pub fn set_int(&mut self, x: i32) { + unsafe { + $set_int_fn(self, x); + } + } + pub fn is_one(&self) -> bool { + unsafe { $is_one_fn(self) == 1 } + } + } + }; +} + +macro_rules! base_field_impl { + ($t:ty, $set_little_endian_fn:ident, $set_little_endian_mod_fn:ident, $set_hash_of_fn:ident, $set_by_csprng_fn:ident, $is_odd_fn:ident, $is_negative_fn:ident, $cmp_fn:ident, $square_root_fn:ident) => { + impl $t { + pub fn set_little_endian(&mut self, buf: &[u8]) -> bool { + unsafe { $set_little_endian_fn(self, buf.as_ptr(), buf.len()) == 0 } + } + pub fn set_little_endian_mod(&mut self, buf: &[u8]) -> bool { + unsafe { $set_little_endian_mod_fn(self, buf.as_ptr(), buf.len()) == 0 } + } + pub fn set_hash_of(&mut self, buf: &[u8]) -> bool { + unsafe { $set_hash_of_fn(self, buf.as_ptr(), buf.len()) == 0 } + } + pub fn set_by_csprng(&mut self) { + unsafe { $set_by_csprng_fn(self) } + } + pub fn is_odd(&self) -> bool { + unsafe { $is_odd_fn(self) == 1 } + } + pub fn is_negative(&self) -> bool { + unsafe { $is_negative_fn(self) == 1 } + } + pub fn cmp(&self, rhs: &$t) -> i32 { + unsafe { $cmp_fn(self, rhs) } + } + pub fn square_root(y: &mut $t, x: &$t) -> bool { + unsafe { $square_root_fn(y, x) == 0 } + } + } + }; +} + +macro_rules! add_op_impl { + ($t:ty, $add_fn:ident, $sub_fn:ident, $neg_fn:ident) => { + impl $t { + pub fn add(z: &mut $t, x: &$t, y: &$t) { + unsafe { $add_fn(z, x, y) } + } + pub fn sub(z: &mut $t, x: &$t, y: &$t) { + unsafe { $sub_fn(z, x, y) } + } + pub fn neg(y: &mut $t, x: &$t) { + unsafe { $neg_fn(y, x) } + } + } + impl<'a> Add for &'a $t { + type Output = $t; + fn add(self, other: &$t) -> $t { + let mut v = unsafe { <$t>::uninit() }; + <$t>::add(&mut v, &self, &other); + v + } + } + impl<'a> AddAssign<&'a $t> for $t { + fn add_assign(&mut self, other: &$t) { + let z: *mut $t = self; + unsafe { + $add_fn(z, z as *const $t, other as *const $t); + } + } + } + impl<'a> Sub for &'a $t { + type Output = $t; + fn sub(self, other: &$t) -> $t { + let mut v = unsafe { <$t>::uninit() }; + <$t>::sub(&mut v, &self, &other); + v + } + } + impl<'a> SubAssign<&'a $t> for $t { + fn sub_assign(&mut self, other: &$t) { + let z: *mut $t = self; + unsafe { + $sub_fn(z, z as *const $t, other as *const $t); + } + } + } + }; +} + +macro_rules! field_mul_op_impl { + ($t:ty, $mul_fn:ident, $div_fn:ident, $inv_fn:ident, $sqr_fn:ident) => { + impl $t { + pub fn mul(z: &mut $t, x: &$t, y: &$t) { + unsafe { $mul_fn(z, x, y) } + } + pub fn div(z: &mut $t, x: &$t, y: &$t) { + unsafe { $div_fn(z, x, y) } + } + pub fn inv(y: &mut $t, x: &$t) { + unsafe { $inv_fn(y, x) } + } + pub fn sqr(y: &mut $t, x: &$t) { + unsafe { $sqr_fn(y, x) } + } + } + impl<'a> Mul for &'a $t { + type Output = $t; + fn mul(self, other: &$t) -> $t { + let mut v = unsafe { <$t>::uninit() }; + <$t>::mul(&mut v, &self, &other); + v + } + } + impl<'a> MulAssign<&'a $t> for $t { + fn mul_assign(&mut self, other: &$t) { + let z: *mut $t = self; + unsafe { + $mul_fn(z, z as *const $t, other as *const $t); + } + } + } + impl<'a> Div for &'a $t { + type Output = $t; + fn div(self, other: &$t) -> $t { + let mut v = unsafe { <$t>::uninit() }; + <$t>::div(&mut v, &self, &other); + v + } + } + impl<'a> DivAssign<&'a $t> for $t { + fn div_assign(&mut self, other: &$t) { + let z: *mut $t = self; + unsafe { + $div_fn(z, z as *const $t, other as *const $t); + } + } + } + }; +} + +macro_rules! ec_impl { + ($t:ty, $dbl_fn:ident, $mul_fn:ident, $normalize_fn:ident, $set_hash_and_map_fn:ident, $mul_vec_fn:ident) => { + impl $t { + pub fn dbl(y: &mut $t, x: &$t) { + unsafe { $dbl_fn(y, x) } + } + pub fn mul(z: &mut $t, x: &$t, y: &mcl_fr) { + unsafe { $mul_fn(z, x, y) } + } + pub fn normalize(y: &mut $t, x: &$t) { + unsafe { $normalize_fn(y, x) } + } + pub fn set_hash_of(&mut self, buf: &[u8]) -> bool { + unsafe { $set_hash_and_map_fn(self, buf.as_ptr(), buf.len()) == 0 } + } + pub fn mul_vec(z: &mut $t, x: &[$t], y: &[mcl_fr]) { + unsafe { $mul_vec_fn(z, x.as_ptr(), y.as_ptr(), x.len()) } + } + } + }; +} + +#[derive(Default, Debug, Clone, Copy, Eq,)] +#[repr(C)] +pub struct mcl_fp { + pub d: [u64; MCLBN_FP_UNIT_SIZE], +} +impl mcl_fp { + pub fn get_order() -> String { + get_field_order() + } +} +common_impl![mcl_fp, mclBnFp_isEqual, mclBnFp_isZero]; +is_valid_impl![mcl_fp, mclBnFp_isValid]; +serialize_impl![ + mcl_fp, + mclBn_getFpByteSize(), + mclBnFp_serialize, + mclBnFp_deserialize +]; +str_impl![mcl_fp, 128, mclBnFp_getStr, mclBnFp_setStr]; +int_impl![mcl_fp, mclBnFp_setInt32, mclBnFp_isOne]; +base_field_impl![ + mcl_fp, + mclBnFp_setLittleEndian, + mclBnFp_setLittleEndianMod, + mclBnFp_setHashOf, + mclBnFp_setByCSPRNG, + mclBnFp_isOdd, + mclBnFp_isNegative, + mclBnFp_cmp, + mclBnFp_squareRoot +]; +add_op_impl![mcl_fp, mclBnFp_add, mclBnFp_sub, mclBnFp_neg]; +field_mul_op_impl![mcl_fp, mclBnFp_mul, mclBnFp_div, mclBnFp_inv, mclBnFp_sqr]; + +#[derive(Debug, Default, Clone, Copy, Eq)] +#[repr(C)] +pub struct mcl_fp2 { + pub d: [mcl_fp; 2], +} +common_impl![mcl_fp2, mclBnFp2_isEqual, mclBnFp2_isZero]; +serialize_impl![ + mcl_fp2, + mclBn_getFpByteSize() * 2, + mclBnFp2_serialize, + mclBnFp2_deserialize +]; +add_op_impl![mcl_fp2, mclBnFp2_add, mclBnFp2_sub, mclBnFp2_neg]; +field_mul_op_impl![mcl_fp2, mclBnFp2_mul, mclBnFp2_div, mclBnFp2_inv, mclBnFp2_sqr]; +impl mcl_fp2 { + pub fn square_root(y: &mut mcl_fp2, x: &mcl_fp2) -> bool { + unsafe { mclBnFp2_squareRoot(y, x) == 0 } + } +} + +#[derive(Debug, Clone, Copy, Eq, Default)] +#[repr(C)] +pub struct mcl_fr { + pub d: [u64; MCLBN_FR_UNIT_SIZE], +} +impl mcl_fr { + pub fn get_order() -> String { + get_curve_order() + } +} +common_impl![mcl_fr, mclBnFr_isEqual, mclBnFr_isZero]; +is_valid_impl![mcl_fr, mclBnFr_isValid]; +serialize_impl![ + mcl_fr, + mclBn_getFrByteSize(), + mclBnFr_serialize, + mclBnFr_deserialize +]; +str_impl![mcl_fr, 128, mclBnFr_getStr, mclBnFr_setStr]; +int_impl![mcl_fr, mclBnFr_setInt32, mclBnFr_isOne]; +base_field_impl![ + mcl_fr, + mclBnFr_setLittleEndian, + mclBnFr_setLittleEndianMod, + mclBnFr_setHashOf, + mclBnFr_setByCSPRNG, + mclBnFr_isOdd, + mclBnFr_isNegative, + mclBnFr_cmp, + mclBnFr_squareRoot +]; +add_op_impl![mcl_fr, mclBnFr_add, mclBnFr_sub, mclBnFr_neg]; +field_mul_op_impl![mcl_fr, mclBnFr_mul, mclBnFr_div, mclBnFr_inv, mclBnFr_sqr]; + +#[derive(Debug, Default, Clone, Copy, Eq)] +#[repr(C)] +pub struct mcl_g1 { + pub x: mcl_fp, + pub y: mcl_fp, + pub z: mcl_fp, +} +common_impl![mcl_g1, mclBnG1_isEqual, mclBnG1_isZero]; +is_valid_impl![mcl_g1, mclBnG1_isValid]; +serialize_impl![ + mcl_g1, + mclBn_getFpByteSize(), + mclBnG1_serialize, + mclBnG1_deserialize +]; +str_impl![mcl_g1, 128 * 3, mclBnG1_getStr, mclBnG1_setStr]; +add_op_impl![mcl_g1, mclBnG1_add, mclBnG1_sub, mclBnG1_neg]; +ec_impl![ + mcl_g1, + mclBnG1_dbl, + mclBnG1_mul, + mclBnG1_normalize, + mclBnG1_hashAndMapTo, + mclBnG1_mulVec +]; + +#[derive(Debug, Default, Clone, Copy, Eq)] +#[repr(C)] +pub struct mcl_g2 { + pub x: mcl_fp2, + pub y: mcl_fp2, + pub z: mcl_fp2, +} +common_impl![mcl_g2, mclBnG2_isEqual, mclBnG2_isZero]; +is_valid_impl![mcl_g2, mclBnG2_isValid]; +serialize_impl![ + mcl_g2, + mclBn_getFpByteSize() * 2, + mclBnG2_serialize, + mclBnG2_deserialize +]; +str_impl![mcl_g2, 128 * 3 * 2, mclBnG2_getStr, mclBnG2_setStr]; +add_op_impl![mcl_g2, mclBnG2_add, mclBnG2_sub, mclBnG2_neg]; +ec_impl![ + mcl_g2, + mclBnG2_dbl, + mclBnG2_mul, + mclBnG2_normalize, + mclBnG2_hashAndMapTo, + mclBnG2_mulVec +]; + +#[derive(Default, Debug, Clone)] +#[repr(C)] +pub struct mcl_gt { + d: [mcl_fp; 12], +} +common_impl![mcl_gt, mclBnGT_isEqual, mclBnGT_isZero]; +serialize_impl![ + mcl_gt, + mclBn_getFpByteSize() * 12, + mclBnGT_serialize, + mclBnGT_deserialize +]; +str_impl![mcl_gt, 128 * 12, mclBnGT_getStr, mclBnGT_setStr]; +int_impl![mcl_gt, mclBnGT_setInt32, mclBnGT_isOne]; +add_op_impl![mcl_gt, mclBnGT_add, mclBnGT_sub, mclBnGT_neg]; +field_mul_op_impl![mcl_gt, mclBnGT_mul, mclBnGT_div, mclBnGT_inv, mclBnGT_sqr]; +impl mcl_gt { + pub fn pow(z: &mut mcl_gt, x: &mcl_gt, y: &mcl_fr) { + unsafe { mclBnGT_pow(z, x, y) } + } +} + +pub fn get_version() -> u32 { + unsafe { mclBn_getVersion() } +} + +pub fn init(curve: CurveType) -> bool { + unsafe { mclBn_init(curve as i32, MCLBN_COMPILED_TIME_VAR) == 0 } +} + +pub fn get_fr_serialized_size() -> u32 { + unsafe { mclBn_getFrByteSize() as u32 } +} + +pub fn get_fp_serialized_size() -> u32 { + unsafe { mclBn_getFpByteSize() as u32 } +} + +pub fn get_g1_serialized_size() -> u32 { + get_fp_serialized_size() +} + +pub fn get_g2_serialized_size() -> u32 { + get_fp_serialized_size() * 2 +} + +pub fn get_gt_serialized_size() -> u32 { + get_fp_serialized_size() * 12 +} + +macro_rules! get_str_impl { + ($get_str_fn:ident) => {{ + let u = MaybeUninit::<[u8; 256]>::uninit(); + let mut buf = unsafe { u.assume_init() }; + let n: usize; + unsafe { + n = $get_str_fn(buf.as_mut_ptr(), buf.len()); + } + if n == 0 { + panic!("get_str"); + } + unsafe { core::str::from_utf8_unchecked(&buf[0..n]).into() } + }}; +} + +pub fn get_field_order() -> String { + get_str_impl![mclBn_getFieldOrder] +} + +pub fn get_curve_order() -> String { + get_str_impl![mclBn_getCurveOrder] +} + +pub fn pairing(z: &mut mcl_gt, x: &mcl_g1, y: &mcl_g2) { + unsafe { + mclBn_pairing(z, x, y); + } +} + +pub fn miller_loop(z: &mut mcl_gt, x: &mcl_g1, y: &mcl_g2) { + unsafe { + mclBn_millerLoop(z, x, y); + } +} + +pub fn final_exp(y: &mut mcl_gt, x: &mcl_gt) { + unsafe { + mclBn_finalExp(y, x); + } +} + +static MCL_INIT: OnceCell = OnceCell::new(); + +pub fn try_init_mcl() { + MCL_INIT.get_or_init(|| { + init(CurveType::BLS12_381) + }); +} \ No newline at end of file diff --git a/mcl/src/recovery.rs b/mcl/src/recovery.rs new file mode 100644 index 000000000..156f97857 --- /dev/null +++ b/mcl/src/recovery.rs @@ -0,0 +1,195 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec::Vec; + +use kzg::{FFTFr, Fr, PolyRecover, ZeroPoly}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; +use crate::types::poly::MclPoly; +use once_cell::sync::OnceCell; + +#[cfg(feature = "parallel")] +use rayon::prelude::*; + +const SCALE_FACTOR: u64 = 5; +static INVERSE_FACTORS: OnceCell> = OnceCell::new(); +static UNSCALE_FACTOR_POWERS: OnceCell> = OnceCell::new(); + +pub fn scale_poly(p: &mut [MclFr], len_p: usize) { + let factors = INVERSE_FACTORS.get_or_init(|| { + let scale_factor = MclFr::from_u64(SCALE_FACTOR); + let inv_factor = MclFr::inverse(&scale_factor); + let mut temp = Vec::with_capacity(65536); + temp.push(MclFr::one()); + for i in 1..65536 { + temp.push(temp[i - 1].mul(&inv_factor)); + } + temp + }); + + p.iter_mut() + .zip(factors) + .take(len_p) + .skip(1) + .for_each(|(p, factor)| { + *p = p.mul(factor); + }); +} + +pub fn unscale_poly(p: &mut [MclFr], len_p: usize) { + let factors = UNSCALE_FACTOR_POWERS.get_or_init(|| { + let scale_factor = MclFr::from_u64(SCALE_FACTOR); + let mut temp = Vec::with_capacity(65536); + temp.push(MclFr::one()); + for i in 1..65536 { + temp.push(temp[i - 1].mul(&scale_factor)); + } + temp + }); + + p.iter_mut() + .zip(factors) + .take(len_p) + .skip(1) + .for_each(|(p, factor)| { + *p = p.mul(factor); + }); +} + +impl PolyRecover for MclPoly { + fn recover_poly_coeffs_from_samples( + samples: &[Option], + fs: &MclFFTSettings, + ) -> Result { + let len_samples = samples.len(); + + if !len_samples.is_power_of_two() { + return Err(String::from( + "Samples must have a length that is a power of two", + )); + } + + let mut missing = Vec::with_capacity(len_samples / 2); + + for (i, sample) in samples.iter().enumerate() { + if sample.is_none() { + missing.push(i); + } + } + + if missing.len() > len_samples / 2 { + return Err(String::from( + "Impossible to recover, too many shards are missing", + )); + } + + // Calculate `Z_r,I` + let (zero_eval, mut zero_poly) = fs.zero_poly_via_multiplication(len_samples, &missing)?; + + // Construct E * Z_r,I: the loop makes the evaluation polynomial + let poly_evaluations_with_zero = samples + .iter() + .zip(zero_eval) + .map(|(maybe_sample, zero_eval)| { + debug_assert_eq!(maybe_sample.is_none(), zero_eval.is_zero()); + + match maybe_sample { + Some(sample) => sample.mul(&zero_eval), + None => MclFr::zero(), + } + }) + .collect::>(); + + // Now inverse FFT so that poly_with_zero is (E * Z_r,I)(x) = (D * Z_r,I)(x) + let mut poly_with_zero = fs.fft_fr(&poly_evaluations_with_zero, true).unwrap(); + drop(poly_evaluations_with_zero); + + // x -> k * x + let len_zero_poly = zero_poly.coeffs.len(); + scale_poly(&mut poly_with_zero, len_samples); + scale_poly(&mut zero_poly.coeffs, len_zero_poly); + + // Q1 = (D * Z_r,I)(k * x) + let scaled_poly_with_zero = poly_with_zero; + + // Q2 = Z_r,I(k * x) + let scaled_zero_poly = zero_poly.coeffs; + + // Polynomial division by convolution: Q3 = Q1 / Q2 + #[cfg(feature = "parallel")] + let (eval_scaled_poly_with_zero, eval_scaled_zero_poly) = { + if len_zero_poly - 1 > 1024 { + rayon::join( + || fs.fft_fr(&scaled_poly_with_zero, false).unwrap(), + || fs.fft_fr(&scaled_zero_poly, false).unwrap(), + ) + } else { + ( + fs.fft_fr(&scaled_poly_with_zero, false).unwrap(), + fs.fft_fr(&scaled_zero_poly, false).unwrap(), + ) + } + }; + #[cfg(not(feature = "parallel"))] + let (eval_scaled_poly_with_zero, eval_scaled_zero_poly) = { + ( + fs.fft_fr(&scaled_poly_with_zero, false).unwrap(), + fs.fft_fr(&scaled_zero_poly, false).unwrap(), + ) + }; + drop(scaled_zero_poly); + + let mut eval_scaled_reconstructed_poly = eval_scaled_poly_with_zero; + #[cfg(not(feature = "parallel"))] + let eval_scaled_reconstructed_poly_iter = eval_scaled_reconstructed_poly.iter_mut(); + #[cfg(feature = "parallel")] + let eval_scaled_reconstructed_poly_iter = eval_scaled_reconstructed_poly.par_iter_mut(); + + eval_scaled_reconstructed_poly_iter + .zip(eval_scaled_zero_poly) + .for_each( + |(eval_scaled_reconstructed_poly, eval_scaled_poly_with_zero)| { + *eval_scaled_reconstructed_poly = eval_scaled_reconstructed_poly + .div(&eval_scaled_poly_with_zero) + .unwrap(); + }, + ); + + // The result of the division is D(k * x): + let mut scaled_reconstructed_poly = + fs.fft_fr(&eval_scaled_reconstructed_poly, true).unwrap(); + drop(eval_scaled_reconstructed_poly); + + // k * x -> x + unscale_poly(&mut scaled_reconstructed_poly, len_samples); + + // Finally we have D(x) which evaluates to our original data at the powers of roots of unity + Ok(Self { + coeffs: scaled_reconstructed_poly, + }) + } + + fn recover_poly_from_samples( + samples: &[Option], + fs: &MclFFTSettings, + ) -> Result { + let reconstructed_poly = Self::recover_poly_coeffs_from_samples(samples, fs)?; + + // The evaluation polynomial for D(x) is the reconstructed data: + let reconstructed_data = fs.fft_fr(&reconstructed_poly.coeffs, false).unwrap(); + + // Check all is well + samples + .iter() + .zip(&reconstructed_data) + .for_each(|(sample, reconstructed_data)| { + debug_assert!(sample.is_none() || reconstructed_data.equals(&sample.unwrap())); + }); + + Ok(Self { + coeffs: reconstructed_data, + }) + } +} diff --git a/mcl/src/types/fft_settings.rs b/mcl/src/types/fft_settings.rs new file mode 100644 index 000000000..5a39aecad --- /dev/null +++ b/mcl/src/types/fft_settings.rs @@ -0,0 +1,106 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; + +use kzg::common_utils::reverse_bit_order; +use kzg::{FFTSettings, Fr}; + +use crate::consts::SCALE2_ROOT_OF_UNITY; +use crate::types::fr::MclFr; + +#[derive(Debug, Clone)] +pub struct MclFFTSettings { + pub max_width: usize, + pub root_of_unity: MclFr, + pub roots_of_unity: Vec, + pub brp_roots_of_unity: Vec, + pub reverse_roots_of_unity: Vec, +} + +impl Default for MclFFTSettings { + fn default() -> Self { + Self::new(0).unwrap() + } +} + +impl FFTSettings for MclFFTSettings { + /// Create FFTSettings with roots of unity for a selected scale. Resulting roots will have a magnitude of 2 ^ max_scale. + fn new(scale: usize) -> Result { + if scale >= SCALE2_ROOT_OF_UNITY.len() { + return Err(String::from( + "Scale is expected to be within root of unity matrix row size", + )); + } + + // max_width = 2 ^ max_scale + let max_width: usize = 1 << scale; + let root_of_unity = MclFr::from_u64_arr(&SCALE2_ROOT_OF_UNITY[scale]); + + // create max_width of roots & store them reversed as well + let roots_of_unity = expand_root_of_unity(&root_of_unity, max_width)?; + + let mut brp_roots_of_unity = roots_of_unity.clone(); + brp_roots_of_unity.pop(); + reverse_bit_order(&mut brp_roots_of_unity)?; + + let mut reverse_roots_of_unity = roots_of_unity.clone(); + reverse_roots_of_unity.reverse(); + + Ok(MclFFTSettings { + max_width, + root_of_unity, + reverse_roots_of_unity, + roots_of_unity, + brp_roots_of_unity, + }) + } + + fn get_max_width(&self) -> usize { + self.max_width + } + + fn get_reverse_roots_of_unity_at(&self, i: usize) -> MclFr { + self.reverse_roots_of_unity[i] + } + + fn get_reversed_roots_of_unity(&self) -> &[MclFr] { + &self.reverse_roots_of_unity + } + + fn get_roots_of_unity_at(&self, i: usize) -> MclFr { + self.roots_of_unity[i] + } + + fn get_roots_of_unity(&self) -> &[MclFr] { + &self.roots_of_unity + } + + fn get_brp_roots_of_unity(&self) -> &[MclFr] { + &self.brp_roots_of_unity + } + + fn get_brp_roots_of_unity_at(&self, i: usize) -> MclFr { + self.brp_roots_of_unity[i] + } +} + +/// Multiply a given root of unity by itself until it results in a 1 and result all multiplication values in a vector +pub fn expand_root_of_unity(root: &MclFr, width: usize) -> Result, String> { + let mut generated_powers = vec![MclFr::one(), *root]; + + while !(generated_powers.last().unwrap().is_one()) { + if generated_powers.len() > width { + return Err(String::from("Root of unity multiplied for too long")); + } + + generated_powers.push(generated_powers.last().unwrap().mul(root)); + } + + if generated_powers.len() != width + 1 { + return Err(String::from("Root of unity has invalid scale")); + } + + Ok(generated_powers) +} diff --git a/mcl/src/types/fk20_multi_settings.rs b/mcl/src/types/fk20_multi_settings.rs new file mode 100644 index 000000000..3f6ed8218 --- /dev/null +++ b/mcl/src/types/fk20_multi_settings.rs @@ -0,0 +1,166 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; + +use kzg::common_utils::reverse_bit_order; +use kzg::{FK20MultiSettings, Poly, FFTG1, G1}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; +use crate::types::g1::MclG1; +use crate::types::g2::MclG2; +use crate::types::kzg_settings::MclKZGSettings; +use crate::types::poly::MclPoly; + +use super::fp::MclFp; +use super::g1::FsG1Affine; + +pub struct MclFK20MultiSettings { + pub kzg_settings: MclKZGSettings, + pub chunk_len: usize, + pub x_ext_fft_files: Vec>, +} + +impl Clone for MclFK20MultiSettings { + fn clone(&self) -> Self { + Self { + kzg_settings: self.kzg_settings.clone(), + chunk_len: self.chunk_len, + x_ext_fft_files: self.x_ext_fft_files.clone(), + } + } +} + +impl Default for MclFK20MultiSettings { + fn default() -> Self { + Self { + kzg_settings: MclKZGSettings::default(), + chunk_len: 1, + x_ext_fft_files: vec![], + } + } +} + +impl FK20MultiSettings + for MclFK20MultiSettings +{ + #[allow(clippy::many_single_char_names)] + fn new(ks: &MclKZGSettings, n2: usize, chunk_len: usize) -> Result { + if n2 > ks.fs.max_width { + return Err(String::from( + "n2 must be less than or equal to kzg settings max width", + )); + } else if !n2.is_power_of_two() { + return Err(String::from("n2 must be a power of two")); + } else if n2 < 2 { + return Err(String::from("n2 must be greater than or equal to 2")); + } else if chunk_len > n2 / 2 { + return Err(String::from("chunk_len must be greater or equal to n2 / 2")); + } else if !chunk_len.is_power_of_two() { + return Err(String::from("chunk_len must be a power of two")); + } + + let n = n2 / 2; + let k = n / chunk_len; + + let mut ext_fft_files = Vec::with_capacity(chunk_len); + { + let mut x = Vec::with_capacity(k); + for offset in 0..chunk_len { + let mut start = 0; + if n >= chunk_len + 1 + offset { + start = n - chunk_len - 1 - offset; + } + + let mut i = 0; + let mut j = start; + + while i + 1 < k { + x.push(ks.g1_values_lagrange_brp[j]); + + i += 1; + + if j >= chunk_len { + j -= chunk_len; + } else { + j = 0; + } + } + x.push(MclG1::identity()); + + let ext_fft_file = ks.fs.toeplitz_part_1(&x); + x.clear(); + ext_fft_files.push(ext_fft_file); + } + } + + let ret = Self { + kzg_settings: ks.clone(), + chunk_len, + x_ext_fft_files: ext_fft_files, + }; + + Ok(ret) + } + + fn data_availability(&self, p: &MclPoly) -> Result, String> { + let n = p.len(); + let n2 = n * 2; + + if n2 > self.kzg_settings.fs.max_width { + return Err(String::from( + "n2 must be less than or equal to kzg settings max width", + )); + } + + if !n2.is_power_of_two() { + return Err(String::from("n2 must be a power of two")); + } + + let mut ret = self.data_availability_optimized(p).unwrap(); + reverse_bit_order(&mut ret)?; + + Ok(ret) + } + + fn data_availability_optimized(&self, p: &MclPoly) -> Result, String> { + let n = p.len(); + let n2 = n * 2; + + if n2 > self.kzg_settings.fs.max_width { + return Err(String::from( + "n2 must be less than or equal to kzg settings max width", + )); + } else if !n2.is_power_of_two() { + return Err(String::from("n2 must be a power of two")); + } + + let n = n2 / 2; + let k = n / self.chunk_len; + let k2 = k * 2; + + let mut h_ext_fft = vec![MclG1::identity(); k2]; + + for i in 0..self.chunk_len { + let toeplitz_coeffs = p.toeplitz_coeffs_stride(i, self.chunk_len); + let h_ext_fft_file = self + .kzg_settings + .fs + .toeplitz_part_2(&toeplitz_coeffs, &self.x_ext_fft_files[i]); + + for j in 0..k2 { + h_ext_fft[j] = h_ext_fft[j].add_or_dbl(&h_ext_fft_file[j]); + } + } + + let mut h = self.kzg_settings.fs.toeplitz_part_3(&h_ext_fft); + + h[k..k2].copy_from_slice(&vec![MclG1::identity(); k2 - k]); + + let ret = self.kzg_settings.fs.fft_g1(&h, false).unwrap(); + + Ok(ret) + } +} diff --git a/mcl/src/types/fk20_single_settings.rs b/mcl/src/types/fk20_single_settings.rs new file mode 100644 index 000000000..d928ed252 --- /dev/null +++ b/mcl/src/types/fk20_single_settings.rs @@ -0,0 +1,102 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec::Vec; + +use kzg::common_utils::reverse_bit_order; +use kzg::{FK20SingleSettings, Poly, FFTG1, G1}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; +use crate::types::g1::MclG1; +use crate::types::g2::MclG2; +use crate::types::kzg_settings::MclKZGSettings; +use crate::types::poly::MclPoly; + +use super::fp::MclFp; +use super::g1::FsG1Affine; + +#[derive(Debug, Clone, Default)] +pub struct MclFK20SingleSettings { + pub kzg_settings: MclKZGSettings, + pub x_ext_fft: Vec, +} + +impl FK20SingleSettings + for MclFK20SingleSettings +{ + fn new(kzg_settings: &MclKZGSettings, n2: usize) -> Result { + let n = n2 / 2; + + if n2 > kzg_settings.fs.max_width { + return Err(String::from( + "n2 must be less than or equal to kzg settings max width", + )); + } else if !n2.is_power_of_two() { + return Err(String::from("n2 must be a power of two")); + } else if n2 < 2 { + return Err(String::from("n2 must be greater than or equal to 2")); + } + + let mut x = Vec::with_capacity(n); + for i in 0..n - 1 { + x.push(kzg_settings.g1_values_lagrange_brp[n - 2 - i]); + } + x.push(MclG1::identity()); + + let x_ext_fft = kzg_settings.fs.toeplitz_part_1(&x); + drop(x); + let kzg_settings = kzg_settings.clone(); + + let ret = Self { + kzg_settings, + x_ext_fft, + }; + + Ok(ret) + } + + fn data_availability(&self, p: &MclPoly) -> Result, String> { + let n = p.len(); + let n2 = n * 2; + + if n2 > self.kzg_settings.fs.max_width { + return Err(String::from( + "n2 must be less than or equal to kzg settings max width", + )); + } else if !n2.is_power_of_two() { + return Err(String::from("n2 must be a power of two")); + } + + let mut ret = self.data_availability_optimized(p).unwrap(); + reverse_bit_order(&mut ret)?; + + Ok(ret) + } + + fn data_availability_optimized(&self, p: &MclPoly) -> Result, String> { + let n = p.len(); + let n2 = n * 2; + + if n2 > self.kzg_settings.fs.max_width { + return Err(String::from( + "n2 must be less than or equal to kzg settings max width", + )); + } else if !n2.is_power_of_two() { + return Err(String::from("n2 must be a power of two")); + } + + let toeplitz_coeffs = p.toeplitz_coeffs_step(); + + let h_ext_fft = self + .kzg_settings + .fs + .toeplitz_part_2(&toeplitz_coeffs, &self.x_ext_fft); + + let h = self.kzg_settings.fs.toeplitz_part_3(&h_ext_fft); + + let ret = self.kzg_settings.fs.fft_g1(&h, false).unwrap(); + + Ok(ret) + } +} diff --git a/mcl/src/types/fp.rs b/mcl/src/types/fp.rs new file mode 100644 index 000000000..d805f8903 --- /dev/null +++ b/mcl/src/types/fp.rs @@ -0,0 +1,108 @@ +use kzg::G1Fp; + +use crate::mcl_methods::{mclBnFp_add, mclBnFp_neg, try_init_mcl, mcl_fp}; + +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] +pub struct MclFp(pub mcl_fp); +impl G1Fp for MclFp { + fn one() -> Self { + try_init_mcl(); + + Self(mcl_fp { + d: [ + 8505329371266088957, + 17002214543764226050, + 6865905132761471162, + 8632934651105793861, + 6631298214892334189, + 1582556514881692819, + ], + }) + } + + fn zero() -> Self { + try_init_mcl(); + + Self(mcl_fp { + d: [0, 0, 0, 0, 0, 0], + }) + } + + fn bls12_381_rx_p() -> Self { + try_init_mcl(); + + Self(mcl_fp { + d: [ + 8505329371266088957, + 17002214543764226050, + 6865905132761471162, + 8632934651105793861, + 6631298214892334189, + 1582556514881692819, + ], + }) + } + + fn inverse(&self) -> Option { + try_init_mcl(); + + let mut out: Self = *self; + mcl_fp::inv(&mut out.0, &self.0); + + Some(out) + } + + fn square(&self) -> Self { + try_init_mcl(); + + let mut out: Self = *self; + mcl_fp::sqr(&mut out.0, &self.0); + + out + } + + fn double(&self) -> Self { + try_init_mcl(); + + let mut out: Self = Default::default(); + + unsafe { + mclBnFp_add(&mut out.0, &self.0, &self.0); + } + + out + } + + fn from_underlying_arr(arr: &[u64; 6]) -> Self { + try_init_mcl(); + + Self(mcl_fp { d: *arr }) + } + + fn neg_assign(&mut self) { + try_init_mcl(); + + unsafe { + mclBnFp_neg(&mut self.0, &self.0); + } + } + + fn mul_assign_fp(&mut self, b: &Self) { + try_init_mcl(); + + self.0 *= &b.0; + } + + fn sub_assign_fp(&mut self, b: &Self) { + try_init_mcl(); + + self.0 -= &b.0; + } + + fn add_assign_fp(&mut self, b: &Self) { + try_init_mcl(); + + self.0 += &b.0; + } +} diff --git a/mcl/src/types/fr.rs b/mcl/src/types/fr.rs new file mode 100644 index 000000000..474ce28e9 --- /dev/null +++ b/mcl/src/types/fr.rs @@ -0,0 +1,304 @@ +extern crate alloc; + +use alloc::format; +use alloc::string::String; +use alloc::string::ToString; +use blst::blst_fr_from_uint64; +use blst::blst_scalar; +use blst::blst_scalar_from_fr; +use blst::blst_uint64_from_fr; + +use crate::mcl_methods::mcl_fr; +use crate::mcl_methods::try_init_mcl; + +use kzg::eip_4844::BYTES_PER_FIELD_ELEMENT; +use kzg::Fr; +use kzg::Scalar256; + +#[repr(C)] +#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] +pub struct MclFr(pub mcl_fr); + +impl Fr for MclFr { + fn null() -> Self { + try_init_mcl(); + + Self::from_u64_arr(&[u64::MAX, u64::MAX, u64::MAX, u64::MAX]) + } + + fn zero() -> Self { + try_init_mcl(); + + Self::from_u64(0) + } + + fn one() -> Self { + try_init_mcl(); + + Self::from_u64(1) + } + + #[cfg(feature = "rand")] + fn rand() -> Self { + try_init_mcl(); + + let val: [u64; 4] = [ + rand::random(), + rand::random(), + rand::random(), + rand::random(), + ]; + + let ret = Self::default(); + let mut blst = MclFr::to_blst_fr(&ret); + + unsafe { + blst_fr_from_uint64(&mut blst, val.as_ptr()); + } + + MclFr::from_blst_fr(blst) + } + + fn from_bytes(bytes: &[u8]) -> Result { + bytes + .try_into() + .map_err(|_| { + format!( + "Invalid byte length. Expected {}, got {}", + BYTES_PER_FIELD_ELEMENT, + bytes.len() + ) + }) + .and_then(|bytes: &[u8; BYTES_PER_FIELD_ELEMENT]| { + let mut bls_scalar = blst_scalar::default(); + let mut fr = blst::blst_fr::default(); + unsafe { + blst::blst_scalar_from_bendian(&mut bls_scalar, bytes.as_ptr()); + if !blst::blst_scalar_fr_check(&bls_scalar) { + return Err("Invalid scalar".to_string()); + } + blst::blst_fr_from_scalar(&mut fr, &bls_scalar); + } + Ok(Self{0: mcl_fr{d: fr.l }}) + }) + } + + fn from_bytes_unchecked(bytes: &[u8]) -> Result { + bytes + .try_into() + .map_err(|_| { + format!( + "Invalid byte length. Expected {}, got {}", + BYTES_PER_FIELD_ELEMENT, + bytes.len() + ) + }) + .map(|bytes: &[u8; BYTES_PER_FIELD_ELEMENT]| { + let mut bls_scalar = blst_scalar::default(); + let mut fr = blst::blst_fr::default(); + unsafe { + blst::blst_scalar_from_bendian(&mut bls_scalar, bytes.as_ptr()); + blst::blst_fr_from_scalar(&mut fr, &bls_scalar); + } + Self{0: mcl_fr{d: fr.l }} + }) + } + + fn from_hex(hex: &str) -> Result { + let bytes = hex::decode(&hex[2..]).unwrap(); + Self::from_bytes(&bytes) + } + + fn from_u64_arr(val: &[u64; 4]) -> Self { + try_init_mcl(); + + let ret = Self::default(); + let mut blst = MclFr::to_blst_fr(&ret); + + unsafe { + blst_fr_from_uint64(&mut blst, val.as_ptr()); + } + + MclFr::from_blst_fr(blst) + } + + fn from_u64(val: u64) -> Self { + try_init_mcl(); + + Self::from_u64_arr(&[val, 0, 0, 0]) + } + + fn to_bytes(&self) -> [u8; 32] { + try_init_mcl(); + + let mut scalar = blst_scalar::default(); + let mut bytes = [0u8; 32]; + unsafe { + blst_scalar_from_fr(&mut scalar, &self.to_blst_fr()); + blst::blst_bendian_from_scalar(bytes.as_mut_ptr(), &scalar); + } + + bytes + } + + fn to_u64_arr(&self) -> [u64; 4] { + try_init_mcl(); + + let blst = self.to_blst_fr(); + + let mut val: [u64; 4] = [0; 4]; + unsafe { + blst_uint64_from_fr(val.as_mut_ptr(), &blst); + } + + val + } + + fn is_one(&self) -> bool { + try_init_mcl(); + + self.0.is_one() + } + + fn is_zero(&self) -> bool { + try_init_mcl(); + + self.0.is_zero() + } + + fn is_null(&self) -> bool {try_init_mcl(); + try_init_mcl(); + + let n = Self::null(); + self.0.eq(&n.0) + } + + fn sqr(&self) -> Self { + try_init_mcl(); + + let mut ret = Self::default(); + mcl_fr::sqr(&mut ret.0, &self.0); + ret + } + + fn mul(&self, b: &Self) -> Self { + try_init_mcl(); + + let mut ret = Self::default(); + mcl_fr::mul(&mut ret.0, &self.0, &b.0); + ret + } + + fn add(&self, b: &Self) -> Self { + try_init_mcl(); + + let mut ret = Self::default(); + mcl_fr::add(&mut ret.0, &self.0, &b.0); + ret + } + + fn sub(&self, b: &Self) -> Self { + try_init_mcl(); + + let mut ret = Self::default(); + mcl_fr::sub(&mut ret.0, &self.0, &b.0); + ret + } + + fn eucl_inverse(&self) -> Self { + try_init_mcl(); + + let mut ret = Self::default(); + mcl_fr::inv(&mut ret.0, &self.0); + ret + } + + fn negate(&self) -> Self { + try_init_mcl(); + + let mut ret = Self::default(); + mcl_fr::neg(&mut ret.0, &self.0); + ret + } + + fn inverse(&self) -> Self { + try_init_mcl(); + + let mut ret = Self::default(); + mcl_fr::inv(&mut ret.0, &self.0); + ret + } + + fn pow(&self, n: usize) -> Self { + try_init_mcl(); + + let mut out = Self::one(); + + let mut temp = *self; + let mut n = n; + loop { + if (n & 1) == 1 { + out = out.mul(&temp); + } + n >>= 1; + if n == 0 { + break; + } + + temp = temp.sqr(); + } + + out + } + + fn div(&self, b: &Self) -> Result { + try_init_mcl(); + + if b.is_zero() { + return Ok(*b) + } + + let tmp = b.eucl_inverse(); + let out = self.mul(&tmp); + + Ok(out) + } + + fn equals(&self, b: &Self) -> bool { + try_init_mcl(); + + mcl_fr::eq(&self.0, &b.0) + } + + fn to_scalar(&self) -> Scalar256 { + try_init_mcl(); + + let blst = self.to_blst_fr(); + + let mut blst_scalar = blst_scalar::default(); + unsafe { + blst_scalar_from_fr(&mut blst_scalar, &blst); + } + Scalar256::from_u8(&blst_scalar.b) + } +} + +impl MclFr { + pub fn from_blst_fr(fr: blst::blst_fr) -> Self { + try_init_mcl(); + + Self { + 0: mcl_fr { + d: fr.l + } + } + } + + pub fn to_blst_fr(&self) -> blst::blst_fr { + try_init_mcl(); + + blst::blst_fr { + l: self.0.d + } + } +} \ No newline at end of file diff --git a/mcl/src/types/g1.rs b/mcl/src/types/g1.rs new file mode 100644 index 000000000..159ed2691 --- /dev/null +++ b/mcl/src/types/g1.rs @@ -0,0 +1,410 @@ +extern crate alloc; + +use core::ops::Add; +use core::ops::Sub; + +use alloc::format; +use alloc::string::String; +use alloc::string::ToString; + +use blst::blst_fp; +use blst::blst_p1; +use blst::blst_p1_affine; +use blst::blst_p1_in_g1; +use kzg::eip_4844::BYTES_PER_G1; +use kzg::msm::precompute::PrecomputationTable; +use kzg::G1Affine; +use kzg::G1GetFp; +use kzg::G1LinComb; +use kzg::G1ProjAddAffine; +use kzg::{G1Mul, G1}; + +use crate::consts::{G1_GENERATOR, G1_IDENTITY, G1_NEGATIVE_GENERATOR}; +use crate::kzg_proofs::g1_linear_combination; +use crate::mcl_methods::mcl_fp; +use crate::mcl_methods::mcl_g1; +use crate::mcl_methods::try_init_mcl; +use crate::types::fr::MclFr; + +use super::fp::MclFp; + +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] +pub struct MclG1(pub mcl_g1); + +impl MclG1 { + pub(crate) const fn from_xyz(x: mcl_fp, y: mcl_fp, z: mcl_fp) -> Self { + MclG1(mcl_g1 { x, y, z }) + } + + pub fn from_blst_p1(p1: blst_p1) -> Self { + Self(mcl_g1 { x: mcl_fp{ d: p1.x.l }, y: mcl_fp{ d: p1.y.l }, z: mcl_fp{ d: p1.z.l } }) + + // Self(blst_p1_into_pc_g1projective(&p1)) + } + + pub const fn to_blst_p1(&self) -> blst_p1 { + blst_p1 { x: blst_fp{ l: self.0.x.d } , y: blst_fp{ l: self.0.y.d }, z: blst_fp{ l: self.0.z.d }} + // pc_g1projective_into_blst_p1(self.0) + } +} + +impl G1 for MclG1 { + fn zero() -> Self { + try_init_mcl(); + + Self(mcl_g1 { + x: mcl_fp { + d: [ + 8505329371266088957, + 17002214543764226050, + 6865905132761471162, + 8632934651105793861, + 6631298214892334189, + 1582556514881692819, + ], + }, + y: mcl_fp { + d: [ + 8505329371266088957, + 17002214543764226050, + 6865905132761471162, + 8632934651105793861, + 6631298214892334189, + 1582556514881692819, + ], + }, + z: mcl_fp { + d: [0, 0, 0, 0, 0, 0], + }, + }) + } + + fn identity() -> Self { + try_init_mcl(); + + G1_IDENTITY + } + + fn generator() -> Self { + try_init_mcl(); + + G1_GENERATOR + } + + fn negative_generator() -> Self { + try_init_mcl(); + + G1_NEGATIVE_GENERATOR + } + + #[cfg(feature = "rand")] + fn rand() -> Self { + try_init_mcl(); + + let result: MclG1 = G1_GENERATOR; + result.mul(&kzg::Fr::rand()) + } + + fn from_bytes(bytes: &[u8]) -> Result { + try_init_mcl(); + + bytes + .try_into() + .map_err(|_| { + format!( + "Invalid byte length. Expected {}, got {}", + BYTES_PER_G1, + bytes.len() + ) + }) + .and_then(|bytes: &[u8; BYTES_PER_G1]| { + let mut tmp = blst_p1_affine::default(); + let mut g1 = blst_p1::default(); + unsafe { + // The uncompress routine also checks that the point is on the curve + if blst::blst_p1_uncompress(&mut tmp, bytes.as_ptr()) != blst::BLST_ERROR::BLST_SUCCESS { + return Err("Failed to uncompress".to_string()); + } + blst::blst_p1_from_affine(&mut g1, &tmp); + } + Ok(MclG1::from_blst_p1(g1)) + }) + } + + fn from_hex(hex: &str) -> Result { + let bytes = hex::decode(&hex[2..]).unwrap(); + Self::from_bytes(&bytes) + } + + fn to_bytes(&self) -> [u8; 48] { + try_init_mcl(); + + let mut out = [0u8; BYTES_PER_G1]; + unsafe { + blst::blst_p1_compress(out.as_mut_ptr(), &self.to_blst_p1()); + } + out + } + + fn add_or_dbl(&self, b: &Self) -> Self { + try_init_mcl(); + + let mut out = mcl_g1::default(); + mcl_g1::add(&mut out, &self.0,&b.0); + Self(out) + } + + fn is_inf(&self) -> bool { + try_init_mcl(); + + self.0.get_str(0).eq("0") + } + + fn is_valid(&self) -> bool { + try_init_mcl(); + + let blst = self.to_blst_p1(); + + unsafe { + blst_p1_in_g1(&blst) + } + } + + fn dbl(&self) -> Self { + try_init_mcl(); + + let mut out = mcl_g1::default(); + mcl_g1::dbl(&mut out, &self.0); + Self(out) + } + + fn add(&self, b: &Self) -> Self { + try_init_mcl(); + + Self(self.0.add(&b.0)) + } + + fn sub(&self, b: &Self) -> Self { + try_init_mcl(); + + Self(self.0.sub(&b.0)) + } + + fn equals(&self, b: &Self) -> bool { + try_init_mcl(); + + mcl_g1::eq(&self.0, &b.0) + } + + fn add_or_dbl_assign(&mut self, b: &Self) { + try_init_mcl(); + + self.0 = self.0.add(&b.0); + } + + fn add_assign(&mut self, b: &Self) { + try_init_mcl(); + + self.0 = self.0.add(&b.0); + } + + fn dbl_assign(&mut self) { + try_init_mcl(); + + let mut r = mcl_g1::default(); + mcl_g1::dbl(&mut r, &self.0); + self.0 = r; + } +} + +impl G1GetFp for MclG1 { + fn x(&self) -> &MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&self.0.x) + } + } + + fn y(&self) -> &MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&self.0.y) + } + } + + fn z(&self) -> &MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&self.0.z) + } + } + + fn x_mut(&mut self) -> &mut MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&mut self.0.x) + } + } + + fn y_mut(&mut self) -> &mut MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&mut self.0.y) + } + } + + fn z_mut(&mut self) -> &mut MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&mut self.0.z) + } + } +} + +impl G1Mul for MclG1 { + fn mul(&self, b: &MclFr) -> Self { + try_init_mcl(); + + let mut out = MclG1::default(); + mcl_g1::mul(&mut out.0, &self.0, &b.0); + out + } +} + +impl G1LinComb for MclG1 { + fn g1_lincomb( + points: &[Self], + scalars: &[MclFr], + len: usize, + precomputation: Option<&PrecomputationTable>, + ) -> Self { + try_init_mcl(); + + let mut out = MclG1::default(); + g1_linear_combination(&mut out, points, scalars, len, precomputation); + out + } +} + +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] +pub struct FsG1Affine { + pub x: mcl_fp, + pub y: mcl_fp +} + +impl G1Affine for FsG1Affine { + fn zero() -> Self { + try_init_mcl(); + + Self { + x: { + mcl_fp { + d: [0, 0, 0, 0, 0, 0], + } + }, + y: { + mcl_fp { + d: [0, 0, 0, 0, 0, 0], + } + }, + } + } + + fn into_affine(g1: &MclG1) -> Self { + try_init_mcl(); + + let mut out: mcl_g1 = Default::default(); + mcl_g1::normalize(&mut out, &g1.0); + + Self { + x: out.x, + y: out.y + } + } + + fn into_affines_loc(out: &mut [Self], g1: &[MclG1]) { + try_init_mcl(); + + let mut i = 0; + for g in g1 { + out[i] = Self::into_affine(g); + i += 1; + } + } + + fn to_proj(&self) -> MclG1 { + try_init_mcl(); + + let mut ret: MclG1 = MclG1::generator(); + + ret.0.x = self.x; + ret.0.y = self.y; + + ret + } + + fn x(&self) -> &MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&self.x) + } + } + + fn y(&self) -> &MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&self.y) + } + } + + fn x_mut(&mut self) -> &mut MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&mut self.x) + } + } + + fn y_mut(&mut self) -> &mut MclFp { + try_init_mcl(); + + unsafe { + // Transmute safe due to repr(C) on MclFp + core::mem::transmute(&mut self.y) + } + } + + fn is_infinity(&self) -> bool { + todo!() + } +} + +pub struct MclG1ProjAddAffine; +impl G1ProjAddAffine for MclG1ProjAddAffine { + fn add_assign_affine(_proj: &mut MclG1, _aff: &FsG1Affine) { + todo!() + } + + fn add_or_double_assign_affine(_proj: &mut MclG1, _aff: &FsG1Affine) { + todo!() + } +} diff --git a/mcl/src/types/g2.rs b/mcl/src/types/g2.rs new file mode 100644 index 000000000..697771ca3 --- /dev/null +++ b/mcl/src/types/g2.rs @@ -0,0 +1,138 @@ +extern crate alloc; + +use alloc::format; +use alloc::string::String; +use alloc::string::ToString; + +use kzg::eip_4844::BYTES_PER_G2; +#[cfg(feature = "rand")] +use kzg::Fr; +use kzg::{G2Mul, G2}; + +use crate::consts::{G2_GENERATOR, G2_NEGATIVE_GENERATOR}; +use crate::mcl_methods::mcl_fp; +use crate::mcl_methods::mcl_fp2; +use crate::mcl_methods::mcl_g2; +use crate::mcl_methods::try_init_mcl; +use crate::types::fr::MclFr; + +#[repr(C)] +#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)] +pub struct MclG2(pub mcl_g2); + +impl MclG2 { + pub fn from_blst_p2(p2: blst::blst_p2) -> Self { + try_init_mcl(); + + Self(mcl_g2 { + x: mcl_fp2{ d: [mcl_fp{ d: p2.x.fp[0].l }, mcl_fp{ d: p2.x.fp[1].l }] }, + y: mcl_fp2{ d: [mcl_fp{ d: p2.y.fp[0].l }, mcl_fp{ d: p2.y.fp[1].l }] }, + z: mcl_fp2{ d: [mcl_fp{ d: p2.z.fp[0].l }, mcl_fp{ d: p2.z.fp[1].l }] }, + }) + // Self(blst_p2_into_pc_g2projective(&p2)) + } + + pub const fn to_blst_p2(&self) -> blst::blst_p2 { + blst::blst_p2 { + x: blst::blst_fp2{ fp: [ blst::blst_fp{ l: self.0.x.d[0].d }, blst::blst_fp{ l: self.0.x.d[1].d } ] }, + y: blst::blst_fp2{ fp: [ blst::blst_fp{ l: self.0.y.d[0].d }, blst::blst_fp{ l: self.0.y.d[1].d } ] }, + z: blst::blst_fp2{ fp: [ blst::blst_fp{ l: self.0.z.d[0].d }, blst::blst_fp{ l: self.0.z.d[1].d } ] } + } + + // pc_g2projective_into_blst_p2(self.0) + } + + #[cfg(feature = "rand")] + pub fn rand() -> Self { + try_init_mcl(); + + let result: MclG2 = G2_GENERATOR; + result.mul(&MclFr::rand()) + } +} + +impl G2 for MclG2 { + fn generator() -> Self { + try_init_mcl(); + + G2_GENERATOR + } + + fn negative_generator() -> Self { + try_init_mcl(); + + G2_NEGATIVE_GENERATOR + } + + fn from_bytes(bytes: &[u8]) -> Result { + try_init_mcl(); + + bytes + .try_into() + .map_err(|_| { + format!( + "Invalid byte length. Expected {}, got {}", + BYTES_PER_G2, + bytes.len() + ) + }) + .and_then(|bytes: &[u8; BYTES_PER_G2]| { + use blst::{blst_p2_affine, blst_p2}; + + let mut tmp = blst_p2_affine::default(); + let mut g2 = blst_p2::default(); + unsafe { + // The uncompress routine also checks that the point is on the curve + if blst::blst_p2_uncompress(&mut tmp, bytes.as_ptr()) != blst::BLST_ERROR::BLST_SUCCESS { + return Err("Failed to uncompress".to_string()); + } + blst::blst_p2_from_affine(&mut g2, &tmp); + } + Ok(MclG2::from_blst_p2(g2)) + }) + } + + fn to_bytes(&self) -> [u8; 96] { + todo!() + } + + fn add_or_dbl(&mut self, b: &Self) -> Self { + try_init_mcl(); + + let mut out: mcl_g2 = mcl_g2::default(); + mcl_g2::add(&mut out, &self.0, &b.0); + Self(out) + } + + fn dbl(&self) -> Self { + try_init_mcl(); + + let mut out = mcl_g2::default(); + mcl_g2::dbl(&mut out, &self.0); + Self(out) + } + + fn sub(&self, b: &Self) -> Self { + try_init_mcl(); + + let mut out: mcl_g2 = mcl_g2::default(); + mcl_g2::sub(&mut out, &self.0, &b.0); + Self(out) + } + + fn equals(&self, b: &Self) -> bool { + try_init_mcl(); + + mcl_g2::eq(&self.0, &b.0) + } +} + +impl G2Mul for MclG2 { + fn mul(&self, b: &MclFr) -> Self { + try_init_mcl(); + + let mut out: mcl_g2 = mcl_g2::default(); + mcl_g2::mul(&mut out, &self.0, &b.0); + Self(out) + } +} diff --git a/mcl/src/types/kzg_settings.rs b/mcl/src/types/kzg_settings.rs new file mode 100644 index 000000000..a78b45b50 --- /dev/null +++ b/mcl/src/types/kzg_settings.rs @@ -0,0 +1,399 @@ +extern crate alloc; + +use alloc::string::{String, ToString}; +use alloc::sync::Arc; +use alloc::{vec, vec::Vec}; + +use kzg::eth::c_bindings::CKZGSettings; +use kzg::eth::{self, FIELD_ELEMENTS_PER_EXT_BLOB}; +use kzg::msm::precompute::{precompute, PrecomputationTable}; +use kzg::{FFTFr, FFTSettings, Fr, G1Mul, G2Mul, KZGSettings, Poly, G1, G2}; + +use crate::consts::{G1_GENERATOR, G2_GENERATOR}; +use crate::fft_g1::fft_g1_fast; +use crate::kzg_proofs::{g1_linear_combination, pairings_verify}; +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; +use crate::types::g1::MclG1; +use crate::types::g2::MclG2; +use crate::types::poly::MclPoly; +use crate::utils::PRECOMPUTATION_TABLES; + +use super::fp::MclFp; +use super::g1::FsG1Affine; + +#[derive(Debug, Clone, Default)] +pub struct MclKZGSettings { + pub fs: MclFFTSettings, + pub g1_values_monomial: Vec, + pub g1_values_lagrange_brp: Vec, + pub g2_values_monomial: Vec, + pub precomputation: Option>>, + pub x_ext_fft_columns: Vec>, + pub cell_size: usize, +} + +fn toeplitz_part_1( + field_elements_per_ext_blob: usize, + output: &mut [MclG1], + x: &[MclG1], + s: &MclFFTSettings, +) -> Result<(), String> { + let n = x.len(); + let n2 = n * 2; + let mut x_ext = vec![MclG1::identity(); n2]; + + x_ext[..n].copy_from_slice(x); + + let x_ext = &x_ext[..]; + + /* Ensure the length is valid */ + if x_ext.len() > field_elements_per_ext_blob || !x_ext.len().is_power_of_two() { + return Err("Invalid input size".to_string()); + } + + let roots_stride = field_elements_per_ext_blob / x_ext.len(); + fft_g1_fast(output, x_ext, 1, &s.roots_of_unity, roots_stride); + + Ok(()) +} + +impl KZGSettings for MclKZGSettings { + fn new( + g1_monomial: &[MclG1], + g1_lagrange_brp: &[MclG1], + g2_monomial: &[MclG2], + fft_settings: &MclFFTSettings, + cell_size: usize, + ) -> Result { + if g1_monomial.len() != g1_lagrange_brp.len() { + return Err("G1 point length mismatch".to_string()); + } + + let field_elements_per_blob = g1_monomial.len(); + let field_elements_per_ext_blob = field_elements_per_blob * 2; + + let n = field_elements_per_ext_blob / 2; + let k = n / cell_size; + let k2 = 2 * k; + + let mut points = vec![MclG1::default(); k2]; + let mut x = vec![MclG1::default(); k]; + let mut x_ext_fft_columns = vec![vec![MclG1::default(); cell_size]; k2]; + + for offset in 0..cell_size { + let start = n - cell_size - 1 - offset; + for (i, p) in x.iter_mut().enumerate().take(k - 1) { + let j = start - i * cell_size; + *p = g1_monomial[j]; + } + x[k - 1] = MclG1::identity(); + + toeplitz_part_1(field_elements_per_ext_blob, &mut points, &x, fft_settings)?; + + for row in 0..k2 { + x_ext_fft_columns[row][offset] = points[row]; + } + } + + Ok(Self { + g1_values_monomial: g1_monomial.to_vec(), + g1_values_lagrange_brp: g1_lagrange_brp.to_vec(), + g2_values_monomial: g2_monomial.to_vec(), + fs: fft_settings.clone(), + x_ext_fft_columns, + precomputation: { + precompute(g1_lagrange_brp).ok().flatten().map(Arc::new) + }, + cell_size, + }) + } + + fn commit_to_poly(&self, poly: &MclPoly) -> Result { + if poly.coeffs.len() > self.g1_values_lagrange_brp.len() { + return Err(String::from("Polynomial is longer than secret g1")); + } + + let mut out = MclG1::default(); + g1_linear_combination( + &mut out, + &self.g1_values_lagrange_brp, + &poly.coeffs, + poly.coeffs.len(), + self.get_precomputation(), + ); + + Ok(out) + } + + fn compute_proof_single(&self, p: &MclPoly, x: &MclFr) -> Result { + if p.coeffs.is_empty() { + return Err(String::from("Polynomial must not be empty")); + } + + // `-(x0^n)`, where `n` is `1` + let divisor_0 = x.negate(); + + // Calculate `q = p / (x^n - x0^n)` for our reduced case (see `compute_proof_multi` for + // generic implementation) + let mut out_coeffs = Vec::from(&p.coeffs[1..]); + for i in (1..out_coeffs.len()).rev() { + let tmp = out_coeffs[i].mul(&divisor_0); + out_coeffs[i - 1] = out_coeffs[i - 1].sub(&tmp); + } + + let q = MclPoly { coeffs: out_coeffs }; + + let ret = self.commit_to_poly(&q)?; + + Ok(ret) + } + + fn check_proof_single( + &self, + com: &MclG1, + proof: &MclG1, + x: &MclFr, + y: &MclFr, + ) -> Result { + let x_g2: MclG2 = G2_GENERATOR.mul(x); + let s_minus_x: MclG2 = self.g2_values_monomial[1].sub(&x_g2); + let y_g1 = G1_GENERATOR.mul(y); + let commitment_minus_y: MclG1 = com.sub(&y_g1); + + Ok(pairings_verify( + &commitment_minus_y, + &G2_GENERATOR, + proof, + &s_minus_x, + )) + } + + fn compute_proof_multi(&self, p: &MclPoly, x0: &MclFr, n: usize) -> Result { + if p.coeffs.is_empty() { + return Err(String::from("Polynomial must not be empty")); + } + + if !n.is_power_of_two() { + return Err(String::from("n must be a power of two")); + } + + // Construct x^n - x0^n = (x - x0.w^0)(x - x0.w^1)...(x - x0.w^(n-1)) + let mut divisor = MclPoly { + coeffs: Vec::with_capacity(n + 1), + }; + + // -(x0^n) + let x_pow_n = x0.pow(n); + + divisor.coeffs.push(x_pow_n.negate()); + + // Zeros + for _ in 1..n { + divisor.coeffs.push(Fr::zero()); + } + + // x^n + divisor.coeffs.push(Fr::one()); + + let mut new_polina = p.clone(); + + // Calculate q = p / (x^n - x0^n) + // let q = p.div(&divisor).unwrap(); + let q = new_polina.div(&divisor)?; + + let ret = self.commit_to_poly(&q)?; + + Ok(ret) + } + + fn check_proof_multi( + &self, + com: &MclG1, + proof: &MclG1, + x: &MclFr, + ys: &[MclFr], + n: usize, + ) -> Result { + if !n.is_power_of_two() { + return Err(String::from("n is not a power of two")); + } + + // Interpolate at a coset. + let mut interp = MclPoly { + coeffs: self.fs.fft_fr(ys, true)?, + }; + + let inv_x = x.inverse(); // Not euclidean? + let mut inv_x_pow = inv_x; + for i in 1..n { + interp.coeffs[i] = interp.coeffs[i].mul(&inv_x_pow); + inv_x_pow = inv_x_pow.mul(&inv_x); + } + + // [x^n]_2 + let x_pow = inv_x_pow.inverse(); + + let xn2 = G2_GENERATOR.mul(&x_pow); + + // [s^n - x^n]_2 + let xn_minus_yn = self.g2_values_monomial[n].sub(&xn2); + + // [interpolation_polynomial(s)]_1 + let is1 = self.commit_to_poly(&interp).unwrap(); + + // [commitment - interpolation_polynomial(s)]_1 = [commit]_1 - [interpolation_polynomial(s)]_1 + let commit_minus_interp = com.sub(&is1); + + let ret = pairings_verify(&commit_minus_interp, &G2_GENERATOR, proof, &xn_minus_yn); + + Ok(ret) + } + + fn get_roots_of_unity_at(&self, i: usize) -> MclFr { + self.fs.get_roots_of_unity_at(i) + } + + fn get_fft_settings(&self) -> &MclFFTSettings { + &self.fs + } + + fn get_g1_lagrange_brp(&self) -> &[MclG1] { + &self.g1_values_lagrange_brp + } + + fn get_g1_monomial(&self) -> &[MclG1] { + &self.g1_values_monomial + } + + fn get_g2_monomial(&self) -> &[MclG2] { + &self.g2_values_monomial + } + + fn get_precomputation(&self) -> Option<&PrecomputationTable> { + self.precomputation.as_ref().map(|v| v.as_ref()) + } + + fn get_x_ext_fft_column(&self, index: usize) -> &[MclG1] { + &self.x_ext_fft_columns[index] + } + + fn get_cell_size(&self) -> usize { + self.cell_size + } +} + +impl<'a> TryFrom<&'a CKZGSettings> for MclKZGSettings { + type Error = String; + + fn try_from(settings: &'a CKZGSettings) -> Result { + let roots_of_unity = unsafe { + core::slice::from_raw_parts(settings.roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB + 1) + .iter() + .map(|r| MclFr::from_blst_fr(blst::blst_fr { l: r.l })) + .collect::>() + }; + + let brp_roots_of_unity = unsafe { + core::slice::from_raw_parts(settings.brp_roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB) + .iter() + .map(|r| MclFr::from_blst_fr(blst::blst_fr { l: r.l })) + .collect::>() + }; + + let reverse_roots_of_unity = unsafe { + core::slice::from_raw_parts( + settings.reverse_roots_of_unity, + FIELD_ELEMENTS_PER_EXT_BLOB + 1, + ) + .iter() + .map(|r| MclFr::from_blst_fr(blst::blst_fr { l: r.l })) + .collect::>() + }; + + let fft_settings = MclFFTSettings { + max_width: FIELD_ELEMENTS_PER_EXT_BLOB, + root_of_unity: roots_of_unity[1], + roots_of_unity, + brp_roots_of_unity, + reverse_roots_of_unity, + }; + + Ok(MclKZGSettings { + fs: fft_settings, + g1_values_monomial: unsafe { + core::slice::from_raw_parts( + settings.g1_values_monomial, + eth::FIELD_ELEMENTS_PER_BLOB, + ) + } + .iter() + .map(|r| MclG1::from_blst_p1(blst::blst_p1 { + x: blst::blst_fp { l: r.x.l }, + y: blst::blst_fp { l: r.y.l }, + z: blst::blst_fp { l: r.z.l }, + })) + .collect::>(), + g1_values_lagrange_brp: unsafe { + core::slice::from_raw_parts( + settings.g1_values_lagrange_brp, + eth::FIELD_ELEMENTS_PER_BLOB, + ) + } + .iter() + .map(|r| MclG1::from_blst_p1(blst::blst_p1 { + x: blst::blst_fp { l: r.x.l }, + y: blst::blst_fp { l: r.y.l }, + z: blst::blst_fp { l: r.z.l }, + })) + .collect::>(), + g2_values_monomial: unsafe { + core::slice::from_raw_parts( + settings.g2_values_monomial, + eth::TRUSTED_SETUP_NUM_G2_POINTS, + ) + } + .iter() + .map(|r| MclG2::from_blst_p2(blst::blst_p2 { + x: blst::blst_fp2 { + fp: [ + blst::blst_fp { l: r.x.fp[0].l }, + blst::blst_fp { l: r.x.fp[1].l }, + ], + }, + y: blst::blst_fp2 { + fp: [ + blst::blst_fp { l: r.y.fp[0].l }, + blst::blst_fp { l: r.y.fp[1].l }, + ], + }, + z: blst::blst_fp2 { + fp: [ + blst::blst_fp { l: r.z.fp[0].l }, + blst::blst_fp { l: r.z.fp[1].l }, + ], + }})) + .collect::>(), + x_ext_fft_columns: unsafe { + core::slice::from_raw_parts( + settings.x_ext_fft_columns, + 2 * ((FIELD_ELEMENTS_PER_EXT_BLOB / 2) / eth::FIELD_ELEMENTS_PER_CELL), + ) + } + .iter() + .map(|it| { + unsafe { core::slice::from_raw_parts(*it, eth::FIELD_ELEMENTS_PER_CELL) } + .iter() + .map(|r| MclG1::from_blst_p1(blst::blst_p1 { + x: blst::blst_fp { l: r.x.l }, + y: blst::blst_fp { l: r.y.l }, + z: blst::blst_fp { l: r.z.l }, + })) + .collect::>() + }) + .collect::>(), + precomputation: unsafe { PRECOMPUTATION_TABLES.get_precomputation(settings) }, + cell_size: eth::FIELD_ELEMENTS_PER_CELL, + }) + } +} diff --git a/mcl/src/types/mod.rs b/mcl/src/types/mod.rs new file mode 100644 index 000000000..3be18fd91 --- /dev/null +++ b/mcl/src/types/mod.rs @@ -0,0 +1,9 @@ +pub mod fft_settings; +pub mod fk20_multi_settings; +pub mod fk20_single_settings; +pub mod fp; +pub mod fr; +pub mod g1; +pub mod g2; +pub mod kzg_settings; +pub mod poly; diff --git a/mcl/src/types/poly.rs b/mcl/src/types/poly.rs new file mode 100644 index 000000000..d1b619c4e --- /dev/null +++ b/mcl/src/types/poly.rs @@ -0,0 +1,406 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; + +use kzg::common_utils::{log2_pow2, log2_u64, next_pow_of_2}; +use kzg::{FFTFr, FFTSettings, FFTSettingsPoly, Fr, Poly}; + +use crate::consts::SCALE_FACTOR; +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; + +#[derive(Debug, Clone, Eq, PartialEq, Default)] +pub struct MclPoly { + pub coeffs: Vec, +} + +impl Poly for MclPoly { + fn new(size: usize) -> Self { + Self { + coeffs: vec![MclFr::default(); size], + } + } + + fn get_coeff_at(&self, i: usize) -> MclFr { + self.coeffs[i] + } + + fn set_coeff_at(&mut self, i: usize, x: &MclFr) { + self.coeffs[i] = *x + } + + fn get_coeffs(&self) -> &[MclFr] { + &self.coeffs + } + + fn len(&self) -> usize { + self.coeffs.len() + } + + fn eval(&self, x: &MclFr) -> MclFr { + if self.coeffs.is_empty() { + return MclFr::zero(); + } else if x.is_zero() { + return self.coeffs[0]; + } + + let mut ret = self.coeffs[self.coeffs.len() - 1]; + let mut i = self.coeffs.len() - 2; + loop { + let temp = ret.mul(x); + ret = temp.add(&self.coeffs[i]); + + if i == 0 { + break; + } + i -= 1; + } + + ret + } + + fn scale(&mut self) { + let scale_factor = MclFr::from_u64(SCALE_FACTOR); + let inv_factor = scale_factor.inverse(); + + let mut factor_power = MclFr::one(); + for i in 0..self.coeffs.len() { + factor_power = factor_power.mul(&inv_factor); + self.coeffs[i] = self.coeffs[i].mul(&factor_power); + } + } + + fn unscale(&mut self) { + let scale_factor = MclFr::from_u64(SCALE_FACTOR); + + let mut factor_power = MclFr::one(); + for i in 0..self.coeffs.len() { + factor_power = factor_power.mul(&scale_factor); + self.coeffs[i] = self.coeffs[i].mul(&factor_power); + } + } + + // TODO: analyze how algo works + fn inverse(&mut self, output_len: usize) -> Result { + if output_len == 0 { + return Err(String::from("Can't produce a zero-length result")); + } else if self.coeffs.is_empty() { + return Err(String::from("Can't inverse a zero-length poly")); + } else if self.coeffs[0].is_zero() { + return Err(String::from( + "First coefficient of polynomial mustn't be zero", + )); + } + + let mut ret = MclPoly { + coeffs: vec![MclFr::zero(); output_len], + }; + // If the input polynomial is constant, the remainder of the series is zero + if self.coeffs.len() == 1 { + ret.coeffs[0] = self.coeffs[0].eucl_inverse(); + + return Ok(ret); + } + + let maxd = output_len - 1; + + // Max space for multiplications is (2 * length - 1) + // Don't need the following as its recalculated inside + // let scale: usize = log2_pow2(next_pow_of_2(2 * output_len - 1)); + // let fft_settings = MclFFTSettings::new(scale).unwrap(); + + // To store intermediate results + + // Base case for d == 0 + ret.coeffs[0] = self.coeffs[0].eucl_inverse(); + let mut d: usize = 0; + let mut mask: usize = 1 << log2_u64(maxd); + while mask != 0 { + d = 2 * d + usize::from((maxd & mask) != 0); + mask >>= 1; + + // b.c -> tmp0 (we're using out for c) + // tmp0.length = min_u64(d + 1, b->length + output->length - 1); + let len_temp = (d + 1).min(self.len() + output_len - 1); + let mut tmp0 = self.mul(&ret, len_temp).unwrap(); + + // 2 - b.c -> tmp0 + for i in 0..tmp0.len() { + tmp0.coeffs[i] = tmp0.coeffs[i].negate(); + } + let fr_two = Fr::from_u64(2); + tmp0.coeffs[0] = tmp0.coeffs[0].add(&fr_two); + + // c.(2 - b.c) -> tmp1; + let tmp1 = ret.mul(&tmp0, d + 1).unwrap(); + + for i in 0..tmp1.len() { + ret.coeffs[i] = tmp1.coeffs[i]; + } + } + + if d + 1 != output_len { + return Err(String::from("D + 1 must be equal to output_len")); + } + + Ok(ret) + } + + fn div(&mut self, divisor: &Self) -> Result { + if divisor.len() >= self.len() || divisor.len() < 128 { + // Tunable parameter + self.long_div(divisor) + } else { + self.fast_div(divisor) + } + } + + fn long_div(&mut self, divisor: &Self) -> Result { + if divisor.coeffs.is_empty() { + return Err(String::from("Can't divide by zero")); + } else if divisor.coeffs[divisor.coeffs.len() - 1].is_zero() { + return Err(String::from("Highest coefficient must be non-zero")); + } + + let out_length = self.poly_quotient_length(divisor); + if out_length == 0 { + return Ok(MclPoly { coeffs: vec![] }); + } + + // Special case for divisor.len() == 2 + if divisor.len() == 2 { + let divisor_0 = divisor.coeffs[0]; + let divisor_1 = divisor.coeffs[1]; + + let mut out_coeffs = Vec::from(&self.coeffs[1..]); + for i in (1..out_length).rev() { + out_coeffs[i] = out_coeffs[i].div(&divisor_1).unwrap(); + + let tmp = out_coeffs[i].mul(&divisor_0); + out_coeffs[i - 1] = out_coeffs[i - 1].sub(&tmp); + } + + out_coeffs[0] = out_coeffs[0].div(&divisor_1).unwrap(); + + Ok(MclPoly { coeffs: out_coeffs }) + } else { + let mut out: MclPoly = MclPoly { + coeffs: vec![MclFr::default(); out_length], + }; + + let mut a_pos = self.len() - 1; + let b_pos = divisor.len() - 1; + let mut diff = a_pos - b_pos; + + let mut a = self.coeffs.clone(); + + while diff > 0 { + out.coeffs[diff] = a[a_pos].div(&divisor.coeffs[b_pos]).unwrap(); + + for i in 0..(b_pos + 1) { + let tmp = out.coeffs[diff].mul(&divisor.coeffs[i]); + a[diff + i] = a[diff + i].sub(&tmp); + } + + diff -= 1; + a_pos -= 1; + } + + out.coeffs[0] = a[a_pos].div(&divisor.coeffs[b_pos]).unwrap(); + Ok(out) + } + } + + fn fast_div(&mut self, divisor: &Self) -> Result { + if divisor.coeffs.is_empty() { + return Err(String::from("Cant divide by zero")); + } else if divisor.coeffs[divisor.coeffs.len() - 1].is_zero() { + return Err(String::from("Highest coefficient must be non-zero")); + } + + let m: usize = self.len() - 1; + let n: usize = divisor.len() - 1; + + // If the divisor is larger than the dividend, the result is zero-length + if n > m { + return Ok(MclPoly { coeffs: Vec::new() }); + } + + // Special case for divisor.length == 1 (it's a constant) + if divisor.len() == 1 { + let mut out = MclPoly { + coeffs: vec![MclFr::zero(); self.len()], + }; + for i in 0..out.len() { + out.coeffs[i] = self.coeffs[i].div(&divisor.coeffs[0]).unwrap(); + } + return Ok(out); + } + + let mut a_flip = self.flip().unwrap(); + let mut b_flip = divisor.flip().unwrap(); + + let inv_b_flip = b_flip.inverse(m - n + 1).unwrap(); + let q_flip = a_flip.mul(&inv_b_flip, m - n + 1).unwrap(); + + let out = q_flip.flip().unwrap(); + Ok(out) + } + + fn mul_direct(&mut self, multiplier: &Self, output_len: usize) -> Result { + if self.len() == 0 || multiplier.len() == 0 { + return Ok(MclPoly::new(0)); + } + + let a_degree = self.len() - 1; + let b_degree = multiplier.len() - 1; + + let mut ret = MclPoly { + coeffs: vec![Fr::zero(); output_len], + }; + + // Truncate the output to the length of the output polynomial + for i in 0..(a_degree + 1) { + let mut j = 0; + while (j <= b_degree) && ((i + j) < output_len) { + let tmp = self.coeffs[i].mul(&multiplier.coeffs[j]); + let tmp = ret.coeffs[i + j].add(&tmp); + ret.coeffs[i + j] = tmp; + + j += 1; + } + } + + Ok(ret) + } +} + +impl FFTSettingsPoly for MclFFTSettings { + fn poly_mul_fft( + a: &MclPoly, + b: &MclPoly, + len: usize, + _fs: Option<&MclFFTSettings>, + ) -> Result { + b.mul_fft(a, len) + } +} + +impl MclPoly { + pub fn _poly_norm(&self) -> Self { + let mut ret = self.clone(); + + let mut temp_len: usize = ret.coeffs.len(); + while temp_len > 0 && ret.coeffs[temp_len - 1].is_zero() { + temp_len -= 1; + } + + if temp_len == 0 { + ret.coeffs = Vec::new(); + } else { + ret.coeffs = ret.coeffs[0..temp_len].to_vec(); + } + + ret + } + + pub fn poly_quotient_length(&self, divisor: &Self) -> usize { + if self.len() >= divisor.len() { + self.len() - divisor.len() + 1 + } else { + 0 + } + } + + pub fn pad(&self, out_length: usize) -> Self { + let mut ret = Self { + coeffs: vec![MclFr::zero(); out_length], + }; + + for i in 0..self.len().min(out_length) { + ret.coeffs[i] = self.coeffs[i]; + } + + ret + } + + pub fn flip(&self) -> Result { + let mut ret = MclPoly { + coeffs: vec![MclFr::default(); self.len()], + }; + for i in 0..self.len() { + ret.coeffs[i] = self.coeffs[self.coeffs.len() - i - 1] + } + + Ok(ret) + } + + pub fn mul_fft(&self, multiplier: &Self, output_len: usize) -> Result { + let length = next_pow_of_2(self.len() + multiplier.len() - 1); + + let scale = log2_pow2(length); + let fft_settings = MclFFTSettings::new(scale).unwrap(); + + let a_pad = self.pad(length); + let b_pad = multiplier.pad(length); + + let a_fft: Vec; + let b_fft: Vec; + + #[cfg(feature = "parallel")] + { + if length > 1024 { + let mut a_fft_temp = vec![]; + let mut b_fft_temp = vec![]; + + rayon::join( + || a_fft_temp = fft_settings.fft_fr(&a_pad.coeffs, false).unwrap(), + || b_fft_temp = fft_settings.fft_fr(&b_pad.coeffs, false).unwrap(), + ); + + a_fft = a_fft_temp; + b_fft = b_fft_temp; + } else { + a_fft = fft_settings.fft_fr(&a_pad.coeffs, false).unwrap(); + b_fft = fft_settings.fft_fr(&b_pad.coeffs, false).unwrap(); + } + } + + #[cfg(not(feature = "parallel"))] + { + // Convert Poly to values + a_fft = fft_settings.fft_fr(&a_pad.coeffs, false).unwrap(); + b_fft = fft_settings.fft_fr(&b_pad.coeffs, false).unwrap(); + } + + // Multiply two value ranges + let mut ab_fft = a_fft; + ab_fft.iter_mut().zip(b_fft).for_each(|(a, b)| { + *a = a.mul(&b); + }); + + // Convert value range multiplication to a resulting polynomial + let ab = fft_settings.fft_fr(&ab_fft, true).unwrap(); + drop(ab_fft); + + let mut ret = MclPoly { + coeffs: vec![MclFr::zero(); output_len], + }; + + let range = ..output_len.min(length); + ret.coeffs[range].clone_from_slice(&ab[range]); + + Ok(ret) + } + + pub fn mul(&mut self, multiplier: &Self, output_len: usize) -> Result { + if self.len() < 64 || multiplier.len() < 64 || output_len < 128 { + // Tunable parameter + self.mul_direct(multiplier, output_len) + } else { + self.mul_fft(multiplier, output_len) + } + } +} diff --git a/mcl/src/utils.rs b/mcl/src/utils.rs new file mode 100644 index 000000000..007f15cab --- /dev/null +++ b/mcl/src/utils.rs @@ -0,0 +1,177 @@ +extern crate alloc; + +use alloc::boxed::Box; +use alloc::vec::Vec; + +use kzg::eip_4844::{hash_to_bls_field, PrecomputationTableManager, BYTES_PER_FIELD_ELEMENT}; +use kzg::eth::c_bindings::{Blob, CKZGSettings, CKzgRet}; +use kzg::{Fr, G1Mul, G2Mul}; + +use crate::consts::{G1_GENERATOR, G2_GENERATOR}; +use crate::types::fp::MclFp; +use crate::types::fr::MclFr; +use crate::types::g1::{MclG1, FsG1Affine}; +use crate::types::g2::MclG2; +use crate::types::kzg_settings::MclKZGSettings; + +pub fn generate_trusted_setup( + n: usize, + secret: [u8; 32usize], +) -> (Vec, Vec, Vec) { + let s = hash_to_bls_field(&secret); + let mut s_pow = Fr::one(); + + let mut s1 = Vec::with_capacity(n); + let mut s2 = Vec::with_capacity(n); + let mut s3 = Vec::with_capacity(n); + + for _ in 0..n { + s1.push(G1_GENERATOR.mul(&s_pow)); + s2.push(G1_GENERATOR.mul(&s_pow)); // TODO: this should be lagrange form + s3.push(G2_GENERATOR.mul(&s_pow)); + + s_pow = s_pow.mul(&s); + } + + (s1, s2, s3) +} + +pub(crate) unsafe fn deserialize_blob(blob: *const Blob) -> Result, CKzgRet> { + (*blob) + .bytes + .chunks(BYTES_PER_FIELD_ELEMENT) + .map(|chunk| { + let mut bytes = [0u8; BYTES_PER_FIELD_ELEMENT]; + bytes.copy_from_slice(chunk); + if let Ok(result) = MclFr::from_bytes(&bytes) { + Ok(result) + } else { + Err(CKzgRet::BadArgs) + } + }) + .collect::, CKzgRet>>() +} + +macro_rules! handle_ckzg_badargs { + ($x: expr) => { + match $x { + Ok(value) => value, + Err(_) => return kzg::eth::c_bindings::CKzgRet::BadArgs, + } + }; +} + +pub(crate) use handle_ckzg_badargs; + +pub(crate) static mut PRECOMPUTATION_TABLES: PrecomputationTableManager< + MclFr, + MclG1, + MclFp, + FsG1Affine, +> = PrecomputationTableManager::new(); + +pub(crate) fn kzg_settings_to_c(rust_settings: &MclKZGSettings) -> CKZGSettings { + use kzg::eth::c_bindings::{blst_fp, blst_fp2, blst_fr, blst_p1, blst_p2}; + + CKZGSettings { + roots_of_unity: Box::leak( + rust_settings + .fs + .roots_of_unity + .iter() + .map(|r| blst_fr { l: r.to_blst_fr().l } ) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + brp_roots_of_unity: Box::leak( + rust_settings + .fs + .brp_roots_of_unity + .iter() + .map(|r| blst_fr { l: r.to_blst_fr().l }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + reverse_roots_of_unity: Box::leak( + rust_settings + .fs + .reverse_roots_of_unity + .iter() + .map(|r| blst_fr { l: r.to_blst_fr().l }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + g1_values_monomial: Box::leak( + rust_settings + .g1_values_monomial + .iter() + .map(|r| blst_p1 { + x: blst_fp { l: r.0.x.d }, + y: blst_fp { l: r.0.y.d }, + z: blst_fp { l: r.0.z.d }, + }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + g1_values_lagrange_brp: Box::leak( + rust_settings + .g1_values_lagrange_brp + .iter() + .map(|r| blst_p1 { + x: blst_fp { l: r.0.x.d }, + y: blst_fp { l: r.0.y.d }, + z: blst_fp { l: r.0.z.d }, + }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + g2_values_monomial: Box::leak( + rust_settings + .g2_values_monomial + .iter() + .map(|r| blst_p2 { + x: blst_fp2 { + fp: [blst_fp { l: r.0.x.d[0].d }, blst_fp { l: r.0.x.d[1].d }], + }, + y: blst_fp2 { + fp: [blst_fp { l: r.0.y.d[0].d }, blst_fp { l: r.0.y.d[1].d }], + }, + z: blst_fp2 { + fp: [blst_fp { l: r.0.z.d[0].d }, blst_fp { l: r.0.z.d[1].d }], + }, + }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + x_ext_fft_columns: Box::leak( + rust_settings + .x_ext_fft_columns + .iter() + .map(|r| { + Box::leak( + r.iter() + .map(|r| blst_p1 { + x: blst_fp { l: r.0.x.d }, + y: blst_fp { l: r.0.y.d }, + z: blst_fp { l: r.0.z.d }, + }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr() + }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + tables: core::ptr::null_mut(), + wbits: 0, + scratch_size: 0, + } +} diff --git a/mcl/src/zero_poly.rs b/mcl/src/zero_poly.rs new file mode 100644 index 000000000..dbe027a3b --- /dev/null +++ b/mcl/src/zero_poly.rs @@ -0,0 +1,314 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; +use core::cmp::{min, Ordering}; + +use kzg::{common_utils::next_pow_of_2, FFTFr, Fr, ZeroPoly}; + +use crate::types::fft_settings::MclFFTSettings; +use crate::types::fr::MclFr; +use crate::types::poly::MclPoly; + +#[cfg(feature = "parallel")] +use rayon::prelude::*; +use smallvec::{smallvec, SmallVec}; + +// Can be tuned & optimized (must be a power of 2) +const DEGREE_OF_PARTIAL: usize = 256; +// Can be tuned & optimized (but must be a power of 2) +const REDUCTION_FACTOR: usize = 4; + +/// Pad given poly it with zeros to new length +pub fn pad_poly(mut poly: Vec, new_length: usize) -> Result, String> { + if new_length < poly.len() { + return Err(String::from( + "new_length must be longer or equal to poly length", + )); + } + + poly.resize(new_length, MclFr::zero()); + + Ok(poly) +} + +/// Pad given poly coefficients it with zeros to new length +pub fn pad_poly_coeffs( + mut coeffs: SmallVec<[T; N]>, + new_length: usize, +) -> Result, String> +where + T: Default + Clone, +{ + if new_length < coeffs.len() { + return Err(String::from( + "new_length must be longer or equal to coeffs length", + )); + } + + coeffs.resize(new_length, T::default()); + + Ok(coeffs) +} + +impl MclFFTSettings { + fn do_zero_poly_mul_partial( + &self, + idxs: &[usize], + stride: usize, + ) -> Result, String> { + if idxs.is_empty() { + return Err(String::from("idx array must not be empty")); + } + + // Makes use of long multiplication in terms of (x - w_0)(x - w_1).. + let mut coeffs = SmallVec::<[MclFr; DEGREE_OF_PARTIAL]>::new(); + + // For the first member, store -w_0 as constant term + coeffs.push(self.roots_of_unity[idxs[0] * stride].negate()); + + for (i, idx) in idxs.iter().copied().enumerate().skip(1) { + // For member (x - w_i) take coefficient as -(w_i + w_{i-1} + ...) + let neg_di = self.roots_of_unity[idx * stride].negate(); + coeffs.push(neg_di.add(&coeffs[i - 1])); + + // Multiply all previous members by (x - w_i) + // It equals multiplying by - w_i and adding x^(i - 1) coefficient (implied multiplication by x) + for j in (1..i).rev() { + coeffs[j] = coeffs[j].mul(&neg_di).add(&coeffs[j - 1]); + } + + // Multiply x^0 member by - w_i + coeffs[0] = coeffs[0].mul(&neg_di); + } + + coeffs.resize(idxs.len() + 1, MclFr::one()); + + Ok(coeffs) + } + + fn reduce_partials( + &self, + domain_size: usize, + partial_coeffs: SmallVec<[SmallVec<[MclFr; DEGREE_OF_PARTIAL]>; REDUCTION_FACTOR]>, + ) -> Result, String> { + if !domain_size.is_power_of_two() { + return Err(String::from("Expected domain size to be a power of 2")); + } + + if partial_coeffs.is_empty() { + return Err(String::from("partials must not be empty")); + } + + // Calculate the resulting polynomial degree + // E.g. (a * x^n + ...) (b * x^m + ...) has a degree of x^(n+m) + let out_degree = partial_coeffs + .iter() + .map(|partial| { + // TODO: Not guaranteed by function signature that this doesn't underflow + partial.len() - 1 + }) + .sum::(); + + if out_degree + 1 > domain_size { + return Err(String::from( + "Out degree is longer than possible polynomial size in domain", + )); + } + + let mut partial_coeffs = partial_coeffs.into_iter(); + + // Pad all partial polynomials to same length, compute their FFT and multiply them together + let mut padded_partial = pad_poly_coeffs( + partial_coeffs + .next() + .expect("Not empty, checked above; qed"), + domain_size, + )?; + let mut eval_result: SmallVec<[MclFr; DEGREE_OF_PARTIAL]> = + smallvec![MclFr::zero(); domain_size]; + self.fft_fr_output(&padded_partial, false, &mut eval_result)?; + + for partial in partial_coeffs { + padded_partial = pad_poly_coeffs(partial, domain_size)?; + let mut evaluated_partial: SmallVec<[MclFr; DEGREE_OF_PARTIAL]> = + smallvec![MclFr::zero(); domain_size]; + self.fft_fr_output(&padded_partial, false, &mut evaluated_partial)?; + + eval_result + .iter_mut() + .zip(evaluated_partial.iter()) + .for_each(|(eval_result, evaluated_partial)| { + *eval_result = eval_result.mul(evaluated_partial); + }); + } + + let mut coeffs = smallvec![MclFr::zero(); domain_size]; + // Apply an inverse FFT to produce a new poly. Limit its size to out_degree + 1 + self.fft_fr_output(&eval_result, true, &mut coeffs)?; + coeffs.truncate(out_degree + 1); + + Ok(coeffs) + } +} + +impl ZeroPoly for MclFFTSettings { + fn do_zero_poly_mul_partial(&self, idxs: &[usize], stride: usize) -> Result { + self.do_zero_poly_mul_partial(idxs, stride) + .map(|coeffs| MclPoly { + coeffs: coeffs.into_vec(), + }) + } + + fn reduce_partials(&self, domain_size: usize, partials: &[MclPoly]) -> Result { + self.reduce_partials( + domain_size, + partials + .iter() + .map(|partial| SmallVec::from_slice(&partial.coeffs)) + .collect(), + ) + .map(|coeffs| MclPoly { + coeffs: coeffs.into_vec(), + }) + } + + fn zero_poly_via_multiplication( + &self, + domain_size: usize, + missing_idxs: &[usize], + ) -> Result<(Vec, MclPoly), String> { + let zero_eval: Vec; + let mut zero_poly: MclPoly; + + if missing_idxs.is_empty() { + zero_eval = Vec::new(); + zero_poly = MclPoly { coeffs: Vec::new() }; + return Ok((zero_eval, zero_poly)); + } + + if missing_idxs.len() >= domain_size { + return Err(String::from("Missing idxs greater than domain size")); + } else if domain_size > self.max_width { + return Err(String::from( + "Domain size greater than fft_settings.max_width", + )); + } else if !domain_size.is_power_of_two() { + return Err(String::from("Domain size must be a power of 2")); + } + + let missing_per_partial = DEGREE_OF_PARTIAL - 1; // Number of missing idxs needed per partial + let domain_stride = self.max_width / domain_size; + + let mut partial_count = 1 + (missing_idxs.len() - 1) / missing_per_partial; // TODO: explain why -1 is used here + + let next_pow: usize = next_pow_of_2(partial_count * DEGREE_OF_PARTIAL); + let domain_ceiling = min(next_pow, domain_size); + // Calculate zero poly + if missing_idxs.len() <= missing_per_partial { + // When all idxs fit into a single multiplication + zero_poly = MclPoly { + coeffs: self + .do_zero_poly_mul_partial(missing_idxs, domain_stride)? + .into_vec(), + }; + } else { + // Otherwise, construct a set of partial polynomials + // Save all constructed polynomials in a shared 'work' vector + let mut work = vec![MclFr::zero(); next_pow]; + + let mut partial_lens = vec![DEGREE_OF_PARTIAL; partial_count]; + + #[cfg(not(feature = "parallel"))] + let iter = missing_idxs + .chunks(missing_per_partial) + .zip(work.chunks_exact_mut(DEGREE_OF_PARTIAL)); + #[cfg(feature = "parallel")] + let iter = missing_idxs + .par_chunks(missing_per_partial) + .zip(work.par_chunks_exact_mut(DEGREE_OF_PARTIAL)); + // Insert all generated partial polynomials at degree_of_partial intervals in work vector + iter.for_each(|(missing_idxs, work)| { + let partial_coeffs = self + .do_zero_poly_mul_partial(missing_idxs, domain_stride) + .expect("`missing_idxs` is guaranteed to not be empty; qed"); + + let partial_coeffs = pad_poly_coeffs(partial_coeffs, DEGREE_OF_PARTIAL).expect( + "`partial.coeffs.len()` (same as `missing_idxs.len() + 1`) is \ + guaranteed to be at most `degree_of_partial`; qed", + ); + work[..DEGREE_OF_PARTIAL].copy_from_slice(&partial_coeffs); + }); + + // Adjust last length to match its actual length + partial_lens[partial_count - 1] = + 1 + missing_idxs.len() - (partial_count - 1) * missing_per_partial; + + // Reduce all vectors into one by reducing them w/ varying size multiplications + while partial_count > 1 { + let reduced_count = 1 + (partial_count - 1) / REDUCTION_FACTOR; + let partial_size = next_pow_of_2(partial_lens[0]); + + // Step over polynomial space and produce larger multiplied polynomials + for i in 0..reduced_count { + let start = i * REDUCTION_FACTOR; + let out_end = min((start + REDUCTION_FACTOR) * partial_size, domain_ceiling); + let reduced_len = min(out_end - start * partial_size, domain_size); + let partials_num = min(REDUCTION_FACTOR, partial_count - start); + + // Calculate partial views from lens and offsets + // Also update offsets to match current iteration + let partial_offset = start * partial_size; + let mut partial_coeffs = SmallVec::new(); + for (partial_offset, partial_len) in (partial_offset..) + .step_by(partial_size) + .zip(partial_lens.iter().skip(i).copied()) + .take(partials_num) + { + // We know the capacity required in `reduce_partials()` call below to avoid + // re-allocation + let mut coeffs = SmallVec::with_capacity(reduced_len); + coeffs.extend_from_slice(&work[partial_offset..][..partial_len]); + partial_coeffs.push(coeffs); + } + + if partials_num > 1 { + let mut reduced_coeffs = + self.reduce_partials(reduced_len, partial_coeffs)?; + // Update partial length to match its length after reduction + partial_lens[i] = reduced_coeffs.len(); + reduced_coeffs = + pad_poly_coeffs(reduced_coeffs, partial_size * partials_num)?; + work[partial_offset..][..reduced_coeffs.len()] + .copy_from_slice(&reduced_coeffs); + } else { + // Instead of keeping track of remaining polynomials, reuse i'th partial for start'th one + partial_lens[i] = partial_lens[start]; + } + } + + // Number of steps done equals the number of polynomials that we still need to reduce together + partial_count = reduced_count; + } + + zero_poly = MclPoly { coeffs: work }; + } + + // Pad resulting poly to expected + match zero_poly.coeffs.len().cmp(&domain_size) { + Ordering::Less => { + zero_poly.coeffs = pad_poly(zero_poly.coeffs, domain_size)?; + } + Ordering::Equal => {} + Ordering::Greater => { + zero_poly.coeffs.truncate(domain_size); + } + } + + // Evaluate calculated poly + zero_eval = self.fft_fr(&zero_poly.coeffs, false)?; + + Ok((zero_eval, zero_poly)) + } +} diff --git a/mcl/tests/batch_adder.rs b/mcl/tests/batch_adder.rs new file mode 100644 index 000000000..e1e7e9c89 --- /dev/null +++ b/mcl/tests/batch_adder.rs @@ -0,0 +1,74 @@ +#[cfg(test)] +mod tests { + use kzg_bench::tests::msm::batch_adder::{ + test_batch_add, test_batch_add_indexed, test_batch_add_indexed_single_bucket, + test_batch_add_step_n, test_phase_one_p_add_p, test_phase_one_p_add_q, + test_phase_one_p_add_q_twice, test_phase_one_zero_or_neg, test_phase_two_p_add_neg, + test_phase_two_p_add_p, test_phase_two_p_add_q, test_phase_two_zero_add_p, + }; + use rust_kzg_mcl::types::{ + fp::MclFp, + g1::{MclG1, FsG1Affine}, + }; + // use rust_kzg_mcl::types:: + + #[test] + fn test_phase_one_zero_or_neg_() { + test_phase_one_zero_or_neg::(); + } + + #[test] + fn test_phase_one_p_add_p_() { + test_phase_one_p_add_p::(); + } + + #[test] + fn test_phase_one_p_add_q_() { + test_phase_one_p_add_q::(); + } + + #[test] + fn test_phase_one_p_add_q_twice_() { + test_phase_one_p_add_q_twice::(); + } + + #[test] + fn test_phase_two_zero_add_p_() { + test_phase_two_zero_add_p::(); + } + + #[test] + fn test_phase_two_p_add_neg_() { + test_phase_two_p_add_neg::(); + } + + #[test] + fn test_phase_two_p_add_q_() { + test_phase_two_p_add_q::(); + } + + #[test] + fn test_phase_two_p_add_p_() { + test_phase_two_p_add_p::(); + } + + #[test] + fn test_batch_add_() { + test_batch_add::(); + } + + #[test] + fn test_batch_add_step_n_() { + test_batch_add_step_n::(); + } + + #[test] + fn test_batch_add_indexed_() { + test_batch_add_indexed::(); + } + + #[test] + fn test_batch_add_indexed_single_bucket_() { + test_batch_add_indexed_single_bucket::(); + } +} diff --git a/mcl/tests/bls12_381.rs b/mcl/tests/bls12_381.rs new file mode 100644 index 000000000..aca6cacc5 --- /dev/null +++ b/mcl/tests/bls12_381.rs @@ -0,0 +1,122 @@ +#[cfg(test)] +mod tests { + use kzg::common_utils::log_2_byte; + use kzg_bench::tests::bls12_381::{ + fr_div_by_zero, fr_div_works, fr_equal_works, fr_from_uint64_works, fr_is_null_works, + fr_is_one_works, fr_is_zero_works, fr_negate_works, fr_pow_works, fr_uint64s_roundtrip, + g1_identity_is_identity, g1_identity_is_infinity, g1_make_linear_combination, + g1_random_linear_combination, log_2_byte_works, p1_mul_works, p1_sub_works, + p2_add_or_dbl_works, p2_mul_works, p2_sub_works, pairings_work, + }; + + use rust_kzg_mcl::kzg_proofs::{g1_linear_combination, pairings_verify}; + use rust_kzg_mcl::types::fp::MclFp; + use rust_kzg_mcl::types::fr::MclFr; + use rust_kzg_mcl::types::g1::{MclG1, FsG1Affine}; + use rust_kzg_mcl::types::g2::MclG2; + + #[test] + fn log_2_byte_works_() { + log_2_byte_works(&log_2_byte) + } + + #[test] + fn fr_is_null_works_() { + fr_is_null_works::() + } + + #[test] + fn fr_is_zero_works_() { + fr_is_zero_works::() + } + + #[test] + fn fr_is_one_works_() { + fr_is_one_works::() + } + + #[test] + fn fr_from_uint64_works_() { + fr_from_uint64_works::() + } + + #[test] + fn fr_equal_works_() { + fr_equal_works::() + } + + #[test] + fn fr_negate_works_() { + fr_negate_works::() + } + + #[test] + fn fr_pow_works_() { + fr_pow_works::() + } + + #[test] + fn fr_div_works_() { + fr_div_works::() + } + + #[test] + fn fr_div_by_zero_() { + fr_div_by_zero::() + } + + #[test] + fn fr_uint64s_roundtrip_() { + fr_uint64s_roundtrip::() + } + + #[test] + fn p1_mul_works_() { + p1_mul_works::() + } + + #[test] + fn p1_sub_works_() { + p1_sub_works::() + } + + #[test] + fn p2_add_or_dbl_works_() { + p2_add_or_dbl_works::() + } + + #[test] + fn p2_mul_works_() { + p2_mul_works::() + } + + #[test] + fn p2_sub_works_() { + p2_sub_works::() + } + + #[test] + fn g1_identity_is_infinity_() { + g1_identity_is_infinity::() + } + + #[test] + fn g1_identity_is_identity_() { + g1_identity_is_identity::() + } + + #[test] + fn g1_make_linear_combination_() { + g1_make_linear_combination::(&g1_linear_combination) + } + + #[test] + fn g1_random_linear_combination_() { + g1_random_linear_combination::(&g1_linear_combination) + } + + #[test] + fn pairings_work_() { + pairings_work::(&pairings_verify) + } +} diff --git a/mcl/tests/c_bindings.rs b/mcl/tests/c_bindings.rs new file mode 100644 index 000000000..e1193dc94 --- /dev/null +++ b/mcl/tests/c_bindings.rs @@ -0,0 +1,80 @@ +#[cfg(test)] +mod tests { + use kzg_bench::tests::c_bindings::{ + blob_to_kzg_commitment_invalid_blob_test, + compute_blob_kzg_proof_commitment_is_point_at_infinity_test, + compute_blob_kzg_proof_invalid_blob_test, free_trusted_setup_null_ptr_test, + free_trusted_setup_set_all_values_to_null_test, + load_trusted_setup_file_invalid_format_test, load_trusted_setup_file_valid_format_test, + load_trusted_setup_invalid_form_test, load_trusted_setup_invalid_g1_byte_length_test, + load_trusted_setup_invalid_g1_point_test, load_trusted_setup_invalid_g2_byte_length_test, + load_trusted_setup_invalid_g2_point_test, + }; + use rust_kzg_mcl::eip_4844::{ + blob_to_kzg_commitment, compute_blob_kzg_proof, free_trusted_setup, load_trusted_setup, + load_trusted_setup_file, + }; + + #[test] + fn blob_to_kzg_commitment_invalid_blob() { + blob_to_kzg_commitment_invalid_blob_test(blob_to_kzg_commitment, load_trusted_setup_file); + } + + #[test] + fn load_trusted_setup_invalid_g1_byte_length() { + load_trusted_setup_invalid_g1_byte_length_test(load_trusted_setup); + } + + #[test] + fn load_trusted_setup_invalid_g1_point() { + load_trusted_setup_invalid_g1_point_test(load_trusted_setup); + } + + #[test] + fn load_trusted_setup_invalid_g2_byte_length() { + load_trusted_setup_invalid_g2_byte_length_test(load_trusted_setup); + } + + #[test] + fn load_trusted_setup_invalid_g2_point() { + load_trusted_setup_invalid_g2_point_test(load_trusted_setup); + } + + #[test] + fn load_trusted_setup_invalid_form() { + load_trusted_setup_invalid_form_test(load_trusted_setup); + } + + #[test] + fn load_trusted_setup_file_invalid_format() { + load_trusted_setup_file_invalid_format_test(load_trusted_setup_file); + } + + #[test] + fn load_trusted_setup_file_valid_format() { + load_trusted_setup_file_valid_format_test(load_trusted_setup_file); + } + + #[test] + fn free_trusted_setup_null_ptr() { + free_trusted_setup_null_ptr_test(free_trusted_setup); + } + + #[test] + fn free_trusted_setup_set_all_values_to_null() { + free_trusted_setup_set_all_values_to_null_test(free_trusted_setup, load_trusted_setup_file); + } + + #[test] + fn compute_blob_kzg_proof_invalid_blob() { + compute_blob_kzg_proof_invalid_blob_test(compute_blob_kzg_proof, load_trusted_setup_file); + } + + #[test] + fn compute_blob_kzg_proof_commitment_is_point_at_infinity() { + compute_blob_kzg_proof_commitment_is_point_at_infinity_test( + compute_blob_kzg_proof, + load_trusted_setup_file, + ); + } +} diff --git a/mcl/tests/consts.rs b/mcl/tests/consts.rs new file mode 100644 index 000000000..7f6adaf72 --- /dev/null +++ b/mcl/tests/consts.rs @@ -0,0 +1,45 @@ +// #[path = "./local_tests/local_consts.rs"] +// pub mod local_consts; + +#[cfg(test)] +mod tests { + use kzg_bench::tests::consts::{ + expand_roots_is_plausible, new_fft_settings_is_plausible, roots_of_unity_are_plausible, + roots_of_unity_is_the_expected_size, roots_of_unity_out_of_bounds_fails, + }; + use rust_kzg_mcl::consts::SCALE2_ROOT_OF_UNITY; + use rust_kzg_mcl::types::fft_settings::{expand_root_of_unity, MclFFTSettings}; + use rust_kzg_mcl::types::fr::MclFr; + + // Shared tests + #[test] + fn roots_of_unity_is_the_expected_size_() { + roots_of_unity_is_the_expected_size(&SCALE2_ROOT_OF_UNITY); + } + + #[test] + fn roots_of_unity_out_of_bounds_fails_() { + roots_of_unity_out_of_bounds_fails::(); + } + + #[test] + fn roots_of_unity_are_plausible_() { + roots_of_unity_are_plausible::(&SCALE2_ROOT_OF_UNITY); + } + + #[test] + fn expand_roots_is_plausible_() { + expand_roots_is_plausible::(&SCALE2_ROOT_OF_UNITY, &expand_root_of_unity); + } + + #[test] + fn new_fft_settings_is_plausible_() { + new_fft_settings_is_plausible::(); + } + + // Local tests + // #[test] + // fn roots_of_unity_repeat_at_stride_() { + // roots_of_unity_repeat_at_stride::(); + // } +} diff --git a/mcl/tests/das.rs b/mcl/tests/das.rs new file mode 100644 index 000000000..36e790979 --- /dev/null +++ b/mcl/tests/das.rs @@ -0,0 +1,16 @@ +#[cfg(test)] +mod tests { + use kzg_bench::tests::das::{das_extension_test_known, das_extension_test_random}; + use rust_kzg_mcl::types::fft_settings::MclFFTSettings; + use rust_kzg_mcl::types::fr::MclFr; + + #[test] + fn das_extension_test_known_() { + das_extension_test_known::(); + } + + #[test] + fn das_extension_test_random_() { + das_extension_test_random::(); + } +} diff --git a/mcl/tests/eip_4844.rs b/mcl/tests/eip_4844.rs new file mode 100644 index 000000000..63661a4aa --- /dev/null +++ b/mcl/tests/eip_4844.rs @@ -0,0 +1,422 @@ +#[cfg(test)] +mod tests { + use kzg::eip_4844::{ + blob_to_kzg_commitment_rust, blob_to_polynomial, bytes_to_blob, + compute_blob_kzg_proof_rust, compute_kzg_proof_rust, compute_powers, + evaluate_polynomial_in_evaluation_form, verify_blob_kzg_proof_batch_rust, + verify_blob_kzg_proof_rust, verify_kzg_proof_rust, + }; + use kzg::Fr; + + use kzg_bench::tests::eip_4844::{ + blob_to_kzg_commitment_test, bytes_to_bls_field_test, + compute_and_verify_blob_kzg_proof_fails_with_incorrect_proof_test, + compute_and_verify_blob_kzg_proof_test, + compute_and_verify_kzg_proof_fails_with_incorrect_proof_test, + compute_and_verify_kzg_proof_round_trip_test, + compute_and_verify_kzg_proof_within_domain_test, compute_kzg_proof_empty_blob_vector_test, + compute_kzg_proof_incorrect_blob_length_test, + compute_kzg_proof_incorrect_commitments_len_test, + compute_kzg_proof_incorrect_poly_length_test, compute_kzg_proof_incorrect_proofs_len_test, + compute_kzg_proof_test, compute_powers_test, test_vectors_blob_to_kzg_commitment, + test_vectors_compute_blob_kzg_proof, test_vectors_compute_kzg_proof, + test_vectors_verify_blob_kzg_proof, test_vectors_verify_blob_kzg_proof_batch, + test_vectors_verify_kzg_proof, validate_batched_input_test, + verify_kzg_proof_batch_fails_with_incorrect_proof_test, verify_kzg_proof_batch_test, + }; + use rust_kzg_mcl::consts::SCALE2_ROOT_OF_UNITY; + use rust_kzg_mcl::eip_4844::load_trusted_setup_filename_rust; + use rust_kzg_mcl::types::fft_settings::expand_root_of_unity; + use rust_kzg_mcl::types::fp::MclFp; + use rust_kzg_mcl::types::g1::FsG1Affine; + use rust_kzg_mcl::types::{ + fft_settings::MclFFTSettings, fr::MclFr, g1::MclG1, g2::MclG2, kzg_settings::MclKZGSettings, + poly::MclPoly, + }; + + #[test] + pub fn bytes_to_bls_field_test_() { + bytes_to_bls_field_test::(); + } + + #[test] + pub fn compute_powers_test_() { + compute_powers_test::(&compute_powers); + } + + #[test] + pub fn blob_to_kzg_commitment_test_() { + blob_to_kzg_commitment_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + ); + } + + #[test] + pub fn compute_kzg_proof_test_() { + compute_kzg_proof_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &compute_kzg_proof_rust, + &blob_to_polynomial, + &evaluate_polynomial_in_evaluation_form, + ); + } + + #[test] + pub fn compute_and_verify_kzg_proof_round_trip_test_() { + compute_and_verify_kzg_proof_round_trip_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_kzg_proof_rust, + &blob_to_polynomial, + &evaluate_polynomial_in_evaluation_form, + &verify_kzg_proof_rust, + ); + } + + #[test] + pub fn compute_and_verify_kzg_proof_within_domain_test_() { + compute_and_verify_kzg_proof_within_domain_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_kzg_proof_rust, + &blob_to_polynomial, + &evaluate_polynomial_in_evaluation_form, + &verify_kzg_proof_rust, + ); + } + + #[test] + pub fn compute_and_verify_kzg_proof_fails_with_incorrect_proof_test_() { + compute_and_verify_kzg_proof_fails_with_incorrect_proof_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_kzg_proof_rust, + &blob_to_polynomial, + &evaluate_polynomial_in_evaluation_form, + &verify_kzg_proof_rust, + ); + } + + #[test] + pub fn compute_and_verify_blob_kzg_proof_test_() { + compute_and_verify_blob_kzg_proof_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_blob_kzg_proof_rust, + &verify_blob_kzg_proof_rust, + ); + } + + #[test] + pub fn compute_and_verify_blob_kzg_proof_fails_with_incorrect_proof_test_() { + compute_and_verify_blob_kzg_proof_fails_with_incorrect_proof_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_blob_kzg_proof_rust, + &verify_blob_kzg_proof_rust, + ); + } + + #[test] + pub fn verify_kzg_proof_batch_test_() { + verify_kzg_proof_batch_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_blob_kzg_proof_rust, + &verify_blob_kzg_proof_batch_rust, + ); + } + + #[test] + pub fn verify_kzg_proof_batch_fails_with_incorrect_proof_test_() { + verify_kzg_proof_batch_fails_with_incorrect_proof_test::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + &compute_blob_kzg_proof_rust, + &verify_blob_kzg_proof_batch_rust, + ); + } + + #[test] + pub fn test_vectors_blob_to_kzg_commitment_() { + test_vectors_blob_to_kzg_commitment::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &blob_to_kzg_commitment_rust, + &bytes_to_blob, + ); + } + + #[test] + pub fn test_vectors_compute_kzg_proof_() { + test_vectors_compute_kzg_proof::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &compute_kzg_proof_rust, + &bytes_to_blob, + ); + } + + #[test] + pub fn test_vectors_compute_blob_kzg_proof_() { + test_vectors_compute_blob_kzg_proof::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &bytes_to_blob, + &compute_blob_kzg_proof_rust, + ); + } + + #[test] + pub fn test_vectors_verify_kzg_proof_() { + test_vectors_verify_kzg_proof::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >(&load_trusted_setup_filename_rust, &verify_kzg_proof_rust); + } + + #[test] + pub fn test_vectors_verify_blob_kzg_proof_() { + test_vectors_verify_blob_kzg_proof::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &bytes_to_blob, + &verify_blob_kzg_proof_rust, + ); + } + + #[test] + pub fn test_vectors_verify_blob_kzg_proof_batch_() { + test_vectors_verify_blob_kzg_proof_batch::< + MclFr, + MclG1, + MclG2, + MclPoly, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &load_trusted_setup_filename_rust, + &bytes_to_blob, + &verify_blob_kzg_proof_batch_rust, + ); + } + + #[test] + pub fn expand_root_of_unity_too_long() { + let out = expand_root_of_unity(&MclFr::from_u64_arr(&SCALE2_ROOT_OF_UNITY[1]), 1); + assert!(out.is_err()); + } + + #[test] + pub fn expand_root_of_unity_too_short() { + let out = expand_root_of_unity(&MclFr::from_u64_arr(&SCALE2_ROOT_OF_UNITY[1]), 3); + assert!(out.is_err()); + } + + #[test] + pub fn compute_kzg_proof_incorrect_blob_length() { + compute_kzg_proof_incorrect_blob_length_test::(&blob_to_polynomial); + } + + #[test] + pub fn compute_kzg_proof_incorrect_poly_length() { + compute_kzg_proof_incorrect_poly_length_test::< + MclPoly, + MclFr, + MclG1, + MclG2, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >(&evaluate_polynomial_in_evaluation_form); + } + + #[test] + pub fn compute_kzg_proof_empty_blob_vector() { + compute_kzg_proof_empty_blob_vector_test::< + MclPoly, + MclFr, + MclG1, + MclG2, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >(&verify_blob_kzg_proof_batch_rust) + } + + #[test] + pub fn compute_kzg_proof_incorrect_commitments_len() { + compute_kzg_proof_incorrect_commitments_len_test::< + MclPoly, + MclFr, + MclG1, + MclG2, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >(&verify_blob_kzg_proof_batch_rust) + } + + #[test] + pub fn compute_kzg_proof_incorrect_proofs_len() { + compute_kzg_proof_incorrect_proofs_len_test::< + MclPoly, + MclFr, + MclG1, + MclG2, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >(&verify_blob_kzg_proof_batch_rust) + } + + #[test] + pub fn validate_batched_input() { + validate_batched_input_test::< + MclPoly, + MclFr, + MclG1, + MclG2, + MclFFTSettings, + MclKZGSettings, + MclFp, + FsG1Affine, + >( + &verify_blob_kzg_proof_batch_rust, + &load_trusted_setup_filename_rust, + ) + } +} diff --git a/mcl/tests/eip_7594.rs b/mcl/tests/eip_7594.rs new file mode 100644 index 000000000..2afbe013a --- /dev/null +++ b/mcl/tests/eip_7594.rs @@ -0,0 +1,135 @@ +#[cfg(test)] +mod tests { + use kzg::{ + eip_4844::{blob_to_kzg_commitment_rust, bytes_to_blob}, + eth, DAS, + }; + use kzg_bench::tests::{ + eip_4844::generate_random_blob_bytes, + eip_7594::{ + test_vectors_compute_cells_and_kzg_proofs, test_vectors_recover_cells_and_kzg_proofs, + test_vectors_verify_cell_kzg_proof_batch, + }, + utils::get_trusted_setup_path, + }; + use rust_kzg_mcl::{ + eip_4844::load_trusted_setup_filename_rust, + eip_7594::MclBackend, + types::{fr::MclFr, g1::MclG1, kzg_settings::MclKZGSettings}, + }; + + #[test] + pub fn test_vectors_compute_cells_and_kzg_proofs_() { + test_vectors_compute_cells_and_kzg_proofs::( + &load_trusted_setup_filename_rust, + &bytes_to_blob, + ); + } + + #[test] + pub fn test_vectors_recover_cells_and_kzg_proofs_() { + test_vectors_recover_cells_and_kzg_proofs::(&load_trusted_setup_filename_rust); + } + + #[test] + pub fn test_vectors_verify_cell_kzg_proof_batch_() { + test_vectors_verify_cell_kzg_proof_batch::(&load_trusted_setup_filename_rust); + } + + #[test] + pub fn test_recover_cells_and_kzg_proofs_succeeds_random_blob() { + let settings = load_trusted_setup_filename_rust(get_trusted_setup_path().as_str()).unwrap(); + let mut rng = rand::thread_rng(); + + /* Get a random blob */ + let blob_bytes = generate_random_blob_bytes(&mut rng); + let blob: Vec = bytes_to_blob(&blob_bytes).unwrap(); + + let mut cells = + vec![MclFr::default(); eth::CELLS_PER_EXT_BLOB * eth::FIELD_ELEMENTS_PER_CELL]; + let mut proofs = vec![MclG1::default(); eth::CELLS_PER_EXT_BLOB]; + + /* Get the cells and proofs */ + let mut result = >::compute_cells_and_kzg_proofs( + &settings, + Some(&mut cells), + Some(&mut proofs), + &blob, + ); + assert!(result.is_ok()); + + let cell_indices: Vec = (0..).step_by(2).take(eth::CELLS_PER_EXT_BLOB / 2).collect(); + let mut partial_cells = + vec![MclFr::default(); (eth::CELLS_PER_EXT_BLOB / 2) * eth::FIELD_ELEMENTS_PER_CELL]; + + /* Erase half of the cells */ + for i in 0..(eth::CELLS_PER_EXT_BLOB / 2) { + partial_cells[i * eth::FIELD_ELEMENTS_PER_CELL..(i + 1) * eth::FIELD_ELEMENTS_PER_CELL] + .clone_from_slice( + &cells[cell_indices[i] * eth::FIELD_ELEMENTS_PER_CELL + ..(cell_indices[i] + 1) * eth::FIELD_ELEMENTS_PER_CELL], + ); + } + + let mut recovered_cells = + vec![MclFr::default(); eth::CELLS_PER_EXT_BLOB * eth::FIELD_ELEMENTS_PER_CELL]; + let mut recovered_proofs = vec![MclG1::default(); eth::CELLS_PER_EXT_BLOB]; + + /* Reconstruct with half of the cells */ + result = >::recover_cells_and_kzg_proofs( + &settings, + &mut recovered_cells, + Some(&mut recovered_proofs), + &cell_indices, + &partial_cells, + ); + assert!(result.is_ok()); + + /* Check that all of the cells match */ + assert!(recovered_cells == cells, "Cells do not match"); + assert!(recovered_proofs == proofs, "Proofs do not match"); + } + + #[test] + pub fn test_verify_cell_kzg_proof_batch_succeeds_random_blob() { + let settings = load_trusted_setup_filename_rust(get_trusted_setup_path().as_str()).unwrap(); + let mut rng = rand::thread_rng(); + + /* Get a random blob */ + let blob_bytes = generate_random_blob_bytes(&mut rng); + let blob = bytes_to_blob(&blob_bytes).unwrap(); + + /* Get the commitment to the blob */ + let commitment_result = blob_to_kzg_commitment_rust(&blob, &settings); + assert!(commitment_result.is_ok()); + let commitment = commitment_result.unwrap(); + + let mut cells: Vec = + vec![MclFr::default(); eth::CELLS_PER_EXT_BLOB * eth::FIELD_ELEMENTS_PER_CELL]; + let mut proofs = vec![MclG1::default(); eth::CELLS_PER_EXT_BLOB]; + + /* Compute cells and proofs */ + let result = >::compute_cells_and_kzg_proofs( + &settings, + Some(&mut cells), + Some(&mut proofs), + &blob, + ); + assert!(result.is_ok()); + + /* Initialize list of commitments & cell indices */ + let commitments = vec![commitment; eth::CELLS_PER_EXT_BLOB]; + + let cell_indices: Vec = (0..).step_by(1).take(eth::CELLS_PER_EXT_BLOB).collect(); + + /* Verify all the proofs */ + let verify_result = >::verify_cell_kzg_proof_batch( + &settings, + &commitments, + &cell_indices, + &cells, + &proofs, + ); + assert!(verify_result.is_ok()); + } +} diff --git a/mcl/tests/fft_fr.rs b/mcl/tests/fft_fr.rs new file mode 100644 index 000000000..b4ed49444 --- /dev/null +++ b/mcl/tests/fft_fr.rs @@ -0,0 +1,27 @@ +#[cfg(test)] +mod tests { + use kzg_bench::tests::fft_fr::{compare_sft_fft, inverse_fft, roundtrip_fft, stride_fft}; + use rust_kzg_mcl::fft_fr::{fft_fr_fast, fft_fr_slow}; + use rust_kzg_mcl::types::fft_settings::MclFFTSettings; + use rust_kzg_mcl::types::fr::MclFr; + + #[test] + fn compare_sft_fft_() { + compare_sft_fft::(&fft_fr_slow, &fft_fr_fast); + } + + #[test] + fn roundtrip_fft_() { + roundtrip_fft::(); + } + + #[test] + fn inverse_fft_() { + inverse_fft::(); + } + + #[test] + fn stride_fft_() { + stride_fft::(); + } +} diff --git a/mcl/tests/fft_g1.rs b/mcl/tests/fft_g1.rs new file mode 100644 index 000000000..808bd75ed --- /dev/null +++ b/mcl/tests/fft_g1.rs @@ -0,0 +1,38 @@ +#[cfg(test)] +mod tests { + use kzg::G1; + use kzg_bench::tests::fft_g1::{compare_ft_fft, roundtrip_fft, stride_fft}; + use rust_kzg_mcl::consts::G1_GENERATOR; + use rust_kzg_mcl::fft_g1::{fft_g1_fast, fft_g1_slow}; + use rust_kzg_mcl::types::fft_settings::MclFFTSettings; + use rust_kzg_mcl::types::fr::MclFr; + use rust_kzg_mcl::types::g1::MclG1; + + fn make_data(n: usize) -> Vec { + if n == 0 { + return Vec::new(); + } + let mut result: Vec = vec![MclG1::default(); n]; + result[0] = G1_GENERATOR; + for i in 1..n { + result[i] = result[i - 1].add_or_dbl(&G1_GENERATOR) + } + + result + } + + #[test] + fn roundtrip_fft_() { + roundtrip_fft::(&make_data); + } + + #[test] + fn stride_fft_() { + stride_fft::(&make_data); + } + + #[test] + fn compare_sft_fft_() { + compare_ft_fft::(&fft_g1_slow, &fft_g1_fast, &make_data); + } +} diff --git a/mcl/tests/fk20_proofs.rs b/mcl/tests/fk20_proofs.rs new file mode 100644 index 000000000..e492c7bc1 --- /dev/null +++ b/mcl/tests/fk20_proofs.rs @@ -0,0 +1,38 @@ +#[cfg(test)] +mod tests { + use kzg_bench::tests::fk20_proofs::*; + use rust_kzg_mcl::eip_7594::MclBackend; + use rust_kzg_mcl::types::fk20_multi_settings::MclFK20MultiSettings; + use rust_kzg_mcl::types::fk20_single_settings::MclFK20SingleSettings; + use rust_kzg_mcl::utils::generate_trusted_setup; + + #[test] + fn test_fk_single() { + fk_single::(&generate_trusted_setup); + } + + #[test] + fn test_fk_single_strided() { + fk_single_strided::(&generate_trusted_setup); + } + + #[test] + fn test_fk_multi_settings() { + fk_multi_settings::(&generate_trusted_setup); + } + + #[test] + fn test_fk_multi_chunk_len_1_512() { + fk_multi_chunk_len_1_512::(&generate_trusted_setup); + } + + #[test] + fn test_fk_multi_chunk_len_16_512() { + fk_multi_chunk_len_16_512::(&generate_trusted_setup); + } + + #[test] + fn test_fk_multi_chunk_len_16_16() { + fk_multi_chunk_len_16_16::(&generate_trusted_setup); + } +} diff --git a/mcl/tests/kzg_proofs.rs b/mcl/tests/kzg_proofs.rs new file mode 100644 index 000000000..c3e3d62e6 --- /dev/null +++ b/mcl/tests/kzg_proofs.rs @@ -0,0 +1,29 @@ +#[cfg(test)] +mod tests { + use kzg_bench::tests::kzg_proofs::{ + commit_to_nil_poly, commit_to_too_long_poly_returns_err, proof_multi, proof_single, + }; + + use rust_kzg_mcl::eip_7594::MclBackend; + use rust_kzg_mcl::utils::generate_trusted_setup; + + #[test] + pub fn test_proof_single() { + proof_single::(&generate_trusted_setup); + } + + #[test] + pub fn test_commit_to_nil_poly() { + commit_to_nil_poly::(&generate_trusted_setup); + } + + #[test] + pub fn test_commit_to_too_long_poly() { + commit_to_too_long_poly_returns_err::(&generate_trusted_setup); + } + + #[test] + pub fn test_proof_multi() { + proof_multi::(&generate_trusted_setup); + } +} diff --git a/mcl/tests/local_tests/local_consts.rs b/mcl/tests/local_tests/local_consts.rs new file mode 100644 index 000000000..1bf7c775f --- /dev/null +++ b/mcl/tests/local_tests/local_consts.rs @@ -0,0 +1,16 @@ +use kzg::{FFTSettings, Fr}; + +pub fn roots_of_unity_repeat_at_stride>() { + let fs1 = TFFTSettings::new(15).unwrap(); + let fs2 = TFFTSettings::new(16).unwrap(); + let fs3 = TFFTSettings::new(17).unwrap(); + + for i in 0..fs1.get_max_width() { + assert!(fs1 + .get_roots_of_unity_at(i) + .equals(&fs2.get_roots_of_unity_at(i * 2))); + assert!(fs1 + .get_roots_of_unity_at(i) + .equals(&fs3.get_roots_of_unity_at(i * 4))); + } +} diff --git a/mcl/tests/local_tests/local_poly.rs b/mcl/tests/local_tests/local_poly.rs new file mode 100644 index 000000000..5f0a7947c --- /dev/null +++ b/mcl/tests/local_tests/local_poly.rs @@ -0,0 +1,371 @@ +use kzg::{Fr, Poly}; +use rand::rngs::StdRng; +use rand::{RngCore, SeedableRng}; + +use rust_kzg_mcl::types::fr::MclFr; +use rust_kzg_mcl::types::poly::MclPoly; + +pub fn create_poly_of_length_ten() { + let poly = MclPoly::new(10); + assert_eq!(poly.len(), 10); +} + +pub fn poly_pad_works_rand() { + let mut rng = StdRng::seed_from_u64(0); + + for _k in 0..256 { + let poly_length: usize = (1 + (rng.next_u64() % 1000)) as usize; + let mut poly = MclPoly::new(poly_length); + for i in 0..poly.len() { + poly.set_coeff_at(i, &MclFr::rand()); + } + + let padded_poly = poly.pad(1000); + for i in 0..poly_length { + assert!(padded_poly.get_coeff_at(i).equals(&poly.get_coeff_at(i))); + } + for i in poly_length..1000 { + assert!(padded_poly.get_coeff_at(i).equals(&Fr::zero())); + } + } +} + +pub fn poly_eval_check() { + let n: usize = 10; + let mut poly = MclPoly::new(n); + for i in 0..n { + let fr = MclFr::from_u64((i + 1) as u64); + poly.set_coeff_at(i, &fr); + } + let expected = MclFr::from_u64((n * (n + 1) / 2) as u64); + let actual = poly.eval(&MclFr::one()); + assert!(expected.equals(&actual)); +} + +pub fn poly_eval_0_check() { + let n: usize = 7; + let a: usize = 597; + let mut poly = MclPoly::new(n); + for i in 0..n { + let fr = MclFr::from_u64((i + a) as u64); + poly.set_coeff_at(i, &fr); + } + let expected = MclFr::from_u64(a as u64); + let actual = poly.eval(&MclFr::zero()); + assert!(expected.equals(&actual)); +} + +pub fn poly_eval_nil_check() { + let n: usize = 0; + let poly = MclPoly::new(n); + let actual = poly.eval(&MclFr::one()); + assert!(actual.equals(&MclFr::zero())); +} + +pub fn poly_inverse_simple_0() { + // 1 / (1 - x) = 1 + x + x^2 + ... + let d: usize = 16; + let mut p = MclPoly::new(2); + p.set_coeff_at(0, &MclFr::one()); + p.set_coeff_at(1, &MclFr::one()); + p.set_coeff_at(1, &MclFr::negate(&p.get_coeff_at(1))); + let result = p.inverse(d); + assert!(result.is_ok()); + let q = result.unwrap(); + for i in 0..d { + assert!(q.get_coeff_at(i).is_one()); + } +} + +pub fn poly_inverse_simple_1() { + // 1 / (1 + x) = 1 - x + x^2 - ... + let d: usize = 16; + let mut p = MclPoly::new(2); + p.set_coeff_at(0, &MclFr::one()); + p.set_coeff_at(1, &MclFr::one()); + let result = p.inverse(d); + assert!(result.is_ok()); + let q = result.unwrap(); + for i in 0..d { + let mut tmp = q.get_coeff_at(i); + if i & 1 != 0 { + tmp = MclFr::negate(&tmp); + } + assert!(tmp.is_one()); + } +} + +pub const NUM_TESTS: u64 = 10; + +fn test_data(a: usize, b: usize) -> Vec { + // (x^2 - 1) / (x + 1) = x - 1 + let test_0_0 = vec![-1, 0, 1]; + let test_0_1 = vec![1, 1]; + let test_0_2 = vec![-1, 1]; + + // (12x^3 - 11x^2 + 9x + 18) / (4x + 3) = 3x^2 - 5x + 6 + let test_1_0 = vec![18, 9, -11, 12]; + let test_1_1 = vec![3, 4]; + let test_1_2 = vec![6, -5, 3]; + + // (x + 1) / (x^2 - 1) = nil + let test_2_0 = vec![1, 1]; + let test_2_1 = vec![-1, 0, 2]; + let test_2_2 = vec![]; + + // (10x^2 + 20x + 30) / 10 = x^2 + 2x + 3 + let test_3_0 = vec![30, 20, 10]; + let test_3_1 = vec![10]; + let test_3_2 = vec![3, 2, 1]; + + // (x^2 + x) / (x + 1) = x + let test_4_0 = vec![0, 1, 1]; + let test_4_1 = vec![1, 1]; + let test_4_2 = vec![0, 1]; + + // (x^2 + x + 1) / 1 = x^2 + x + 1 + let test_5_0 = vec![1, 1, 1]; + let test_5_1 = vec![1]; + let test_5_2 = vec![1, 1, 1]; + + // (x^2 + x + 1) / (0x + 1) = x^2 + x + 1 + let test_6_0 = vec![1, 1, 1]; + let test_6_1 = vec![1, 0]; // The highest coefficient is zero + let test_6_2 = vec![1, 1, 1]; + + // (x^3) / (x) = (x^2) + let test_7_0 = vec![0, 0, 0, 1]; + let test_7_1 = vec![0, 1]; + let test_7_2 = vec![0, 0, 1]; + + // + let test_8_0 = vec![ + 236, + 945, + -297698, + 2489425, + -18556462, + -301325440, + 2473062655, + -20699887353, + ]; + let test_8_1 = vec![4, 11, -5000, 45541, -454533]; + let test_8_2 = vec![59, 74, -878, 45541]; + + // (x^4 + 2x^3 + 3x^2 + 2x + 1) / (-x^2 -x -1) = (-x^2 -x -1) + let test_9_0 = vec![1, 2, 3, 2, 1]; + let test_9_1 = vec![-1, -1, -1]; + let test_9_2 = vec![-1, -1, -1]; + + let test_data = [ + [test_0_0, test_0_1, test_0_2], + [test_1_0, test_1_1, test_1_2], + [test_2_0, test_2_1, test_2_2], + [test_3_0, test_3_1, test_3_2], + [test_4_0, test_4_1, test_4_2], + [test_5_0, test_5_1, test_5_2], + [test_6_0, test_6_1, test_6_2], + [test_7_0, test_7_1, test_7_2], + [test_8_0, test_8_1, test_8_2], + [test_9_0, test_9_1, test_9_2], + ]; + + test_data[a][b].clone() +} + +fn new_test_poly(coeffs: &[i64]) -> MclPoly { + let mut p = MclPoly::new(0); + + for &coeff in coeffs.iter() { + if coeff >= 0 { + let c = MclFr::from_u64(coeff as u64); + p.coeffs.push(c); + } else { + let c = MclFr::from_u64((-coeff) as u64); + let negc = c.negate(); + p.coeffs.push(negc); + } + } + + p +} + +pub fn poly_div_long_test() { + for i in 0..9 { + // Tests are designed to throw an exception when last member is 0 + if i == 6 { + continue; + } + + let divided_data = test_data(i, 0); + let divisor_data = test_data(i, 1); + let expected_data = test_data(i, 2); + let mut dividend: MclPoly = new_test_poly(÷d_data); + let divisor: MclPoly = new_test_poly(&divisor_data); + let expected: MclPoly = new_test_poly(&expected_data); + + let actual = dividend.long_div(&divisor).unwrap(); + + assert_eq!(expected.len(), actual.len()); + for i in 0..actual.len() { + assert!(expected.get_coeff_at(i).equals(&actual.get_coeff_at(i))) + } + } +} + +pub fn poly_div_fast_test() { + for i in 0..9 { + // Tests are designed to throw an exception when last member is 0 + if i == 6 { + continue; + } + + let divided_data = test_data(i, 0); + let divisor_data = test_data(i, 1); + let expected_data = test_data(i, 2); + let mut dividend: MclPoly = new_test_poly(÷d_data); + let divisor: MclPoly = new_test_poly(&divisor_data); + let expected: MclPoly = new_test_poly(&expected_data); + + let actual = dividend.fast_div(&divisor).unwrap(); + + assert_eq!(expected.len(), actual.len()); + for i in 0..actual.len() { + assert!(expected.get_coeff_at(i).equals(&actual.get_coeff_at(i))) + } + } +} + +pub fn test_poly_div_by_zero() { + let mut dividend = MclPoly::new(2); + + dividend.set_coeff_at(0, &MclFr::from_u64(1)); + dividend.set_coeff_at(1, &MclFr::from_u64(1)); + + let divisor = MclPoly::new(0); + + let dummy = dividend.div(&divisor); + assert!(dummy.is_err()); +} + +pub fn poly_mul_direct_test() { + for i in 0..9 { + let coeffs1 = test_data(i, 2); + let coeffs2 = test_data(i, 1); + let coeffs3 = test_data(i, 0); + + let mut multiplicand: MclPoly = new_test_poly(&coeffs1); + let mut multiplier: MclPoly = new_test_poly(&coeffs2); + let expected: MclPoly = new_test_poly(&coeffs3); + + let result0 = multiplicand.mul_direct(&multiplier, coeffs3.len()).unwrap(); + for j in 0..result0.len() { + assert!(expected.get_coeff_at(j).equals(&result0.get_coeff_at(j))) + } + + // Check commutativity + let result1 = multiplier.mul_direct(&multiplicand, coeffs3.len()).unwrap(); + for j in 0..result1.len() { + assert!(expected.get_coeff_at(j).equals(&result1.get_coeff_at(j))) + } + } +} + +pub fn poly_mul_fft_test() { + for i in 0..9 { + // Ignore 0 multiplication case because its incorrect when multiplied backwards + if i == 2 { + continue; + } + + let coeffs1 = test_data(i, 2); + let coeffs2 = test_data(i, 1); + let coeffs3 = test_data(i, 0); + + let multiplicand: MclPoly = new_test_poly(&coeffs1); + let multiplier: MclPoly = new_test_poly(&coeffs2); + let expected: MclPoly = new_test_poly(&coeffs3); + + let result0 = multiplicand.mul_fft(&multiplier, coeffs3.len()).unwrap(); + for j in 0..result0.len() { + assert!(expected.get_coeff_at(j).equals(&result0.get_coeff_at(j))) + } + + // Check commutativity + let result1 = multiplier.mul_fft(&multiplicand, coeffs3.len()).unwrap(); + for j in 0..result1.len() { + assert!(expected.get_coeff_at(j).equals(&result1.get_coeff_at(j))) + } + } +} + +pub fn poly_mul_random() { + let mut rng = StdRng::seed_from_u64(0); + + for _k in 0..256 { + let multiplicand_length: usize = (1 + (rng.next_u64() % 1000)) as usize; + let mut multiplicand = MclPoly::new(multiplicand_length); + for i in 0..multiplicand.len() { + multiplicand.set_coeff_at(i, &MclFr::rand()); + } + + let multiplier_length: usize = (1 + (rng.next_u64() % 1000)) as usize; + let mut multiplier = MclPoly::new(multiplier_length); + for i in 0..multiplier.len() { + multiplier.set_coeff_at(i, &MclFr::rand()); + } + + if multiplicand.get_coeff_at(multiplicand.len() - 1).is_zero() { + multiplicand.set_coeff_at(multiplicand.len() - 1, &Fr::one()); + } + + if multiplier.get_coeff_at(multiplier.len() - 1).is_zero() { + multiplier.set_coeff_at(multiplier.len() - 1, &Fr::one()); + } + + let out_length: usize = (1 + (rng.next_u64() % 1000)) as usize; + let q0 = multiplicand.mul_direct(&multiplier, out_length).unwrap(); + let q1 = multiplicand.mul_fft(&multiplier, out_length).unwrap(); + + assert_eq!(q0.len(), q1.len()); + for i in 0..q0.len() { + assert!(q0.get_coeff_at(i).equals(&q1.get_coeff_at(i))); + } + } +} + +pub fn poly_div_random() { + let mut rng = StdRng::seed_from_u64(0); + for _k in 0..256 { + let dividend_length: usize = (2 + (rng.next_u64() % 1000)) as usize; + let divisor_length: usize = 1 + ((rng.next_u64() as usize) % dividend_length); + + let mut dividend = MclPoly::new(dividend_length); + let mut divisor = MclPoly::new(divisor_length); + + for i in 0..dividend_length { + dividend.set_coeff_at(i, &MclFr::rand()); + } + + for i in 0..divisor_length { + divisor.set_coeff_at(i, &MclFr::rand()); + } + + //Ensure that the polynomials' orders corresponds to their lengths + if dividend.get_coeff_at(dividend.len() - 1).is_zero() { + dividend.set_coeff_at(dividend.len() - 1, &Fr::one()); + } + + if divisor.get_coeff_at(divisor.len() - 1).is_zero() { + divisor.set_coeff_at(divisor.len() - 1, &Fr::one()); + } + + let result0 = dividend.long_div(&divisor).unwrap(); + let result1 = dividend.fast_div(&divisor).unwrap(); + + assert_eq!(result0.len(), result1.len()); + for i in 0..result0.len() { + assert!(result0.get_coeff_at(i).equals(&result1.get_coeff_at(i))); + } + } +} diff --git a/mcl/tests/local_tests/local_recovery.rs b/mcl/tests/local_tests/local_recovery.rs new file mode 100644 index 000000000..3de2e1f46 --- /dev/null +++ b/mcl/tests/local_tests/local_recovery.rs @@ -0,0 +1,158 @@ +use kzg::{FFTFr, FFTSettings, Fr, Poly, PolyRecover}; +use rand::rngs::StdRng; +use rand::{RngCore, SeedableRng}; +use std::convert::TryInto; + +fn shuffle(a: &mut [usize], n: usize) { + let mut i: u64 = n as u64; + let mut j: usize; + let mut tmp: usize; + + let mut rng = StdRng::seed_from_u64(0); + while i > 0 { + j = (rng.next_u64() % i) as usize; + i -= 1; + tmp = a[j]; + a[j] = a[i as usize]; + a[i as usize] = tmp; + } +} + +fn random_missing( + with_missing: &mut [Option], + data: &[TFr], + len_data: usize, + known: usize, +) { + let mut missing_idx = Vec::new(); + for i in 0..len_data { + missing_idx.push(i); + with_missing[i] = Some(data[i].clone()); + } + + shuffle(&mut missing_idx, len_data); + for i in 0..(len_data - known) { + with_missing[missing_idx[i]] = None; + } +} + +pub fn recover_simple< + TFr: Fr, + TFFTSettings: FFTSettings + FFTFr, + TPoly: Poly, + TPolyRecover: PolyRecover, +>() { + let fs_query = TFFTSettings::new(2); + assert!(fs_query.is_ok()); + + let fs: TFFTSettings = fs_query.unwrap(); + let max_width: usize = fs.get_max_width(); + + let poly_query = TPoly::new(max_width); + let mut poly = poly_query; + + for i in 0..(max_width / 2) { + poly.set_coeff_at(i, &TFr::from_u64(i.try_into().unwrap())); + } + + for i in (max_width / 2)..max_width { + poly.set_coeff_at(i, &TFr::zero()); + } + + let data_query = fs.fft_fr(poly.get_coeffs(), false); + assert!(data_query.is_ok()); + let data = data_query.unwrap(); + + let sample: [Option; 4] = [Some(data[0].clone()), None, None, Some(data[3].clone())]; + + let recovered_query = TPolyRecover::recover_poly_from_samples(&sample, &fs); + assert!(recovered_query.is_ok()); + let recovered = recovered_query.unwrap(); + + for (i, item) in data.iter().enumerate().take(max_width) { + assert!(item.equals(&recovered.get_coeff_at(i))); + } + + let mut recovered_vec: Vec = Vec::new(); + + for i in 0..max_width { + recovered_vec.push(recovered.get_coeff_at(i)); + } + + let back_query = fs.fft_fr(&recovered_vec, true); + assert!(back_query.is_ok()); + let back = back_query.unwrap(); + + for (i, back_x) in back[..(max_width / 2)].iter().enumerate() { + assert!(back_x.equals(&poly.get_coeff_at(i))); + } + + for back_x in back[(max_width / 2)..max_width].iter() { + assert!(back_x.is_zero()); + } +} + +pub fn recover_random< + TFr: Fr, + TFFTSettings: FFTSettings + FFTFr, + TPoly: Poly, + TPolyRecover: PolyRecover, +>() { + let fs_query = TFFTSettings::new(12); + assert!(fs_query.is_ok()); + + let fs: TFFTSettings = fs_query.unwrap(); + let max_width: usize = fs.get_max_width(); + // let mut poly = TPoly::default(); + let poly_query = TPoly::new(max_width); + let mut poly = poly_query; + + for i in 0..(max_width / 2) { + poly.set_coeff_at(i, &TFr::from_u64(i.try_into().unwrap())); + } + + for i in (max_width / 2)..max_width { + poly.set_coeff_at(i, &TFr::zero()); + } + + let data_query = fs.fft_fr(poly.get_coeffs(), false); + assert!(data_query.is_ok()); + let data = data_query.unwrap(); + + let mut samples = vec![Some(TFr::default()); max_width]; // std::vec![TFr; max_width]; + + for i in 0..10 { + let known_ratio = 0.5 + (i as f32) * 0.05; + let known: usize = ((max_width as f32) * known_ratio) as usize; + + for _ in 0..4 { + random_missing(&mut samples, &data, max_width, known); + + let recovered_query = TPolyRecover::recover_poly_from_samples(&samples, &fs); + assert!(recovered_query.is_ok()); + let recovered = recovered_query.unwrap(); + + for (j, item) in data.iter().enumerate().take(max_width) { + assert!(item.equals(&recovered.get_coeff_at(j))); + } + + let mut recovered_vec: Vec = Vec::new(); + + for i in 0..max_width { + recovered_vec.push(recovered.get_coeff_at(i)); + } + + let back_query = fs.fft_fr(&recovered_vec, true); + assert!(back_query.is_ok()); + let back = back_query.unwrap(); + + for (i, back_x) in back[..(max_width / 2)].iter().enumerate() { + assert!(back_x.equals(&poly.get_coeff_at(i))); + } + + for back_x in back[(max_width / 2)..max_width].iter() { + assert!(back_x.is_zero()); + } + } + } +} diff --git a/mcl/tests/local_tests/mod.rs b/mcl/tests/local_tests/mod.rs new file mode 100644 index 000000000..ef310fa97 --- /dev/null +++ b/mcl/tests/local_tests/mod.rs @@ -0,0 +1,3 @@ +pub mod local_consts; +pub mod local_poly; +pub mod local_recovery; diff --git a/mcl/tests/mod.rs b/mcl/tests/mod.rs new file mode 100644 index 000000000..d1b7273bd --- /dev/null +++ b/mcl/tests/mod.rs @@ -0,0 +1 @@ +pub mod local_tests; diff --git a/mcl/tests/poly.rs b/mcl/tests/poly.rs new file mode 100644 index 000000000..0f21ed00a --- /dev/null +++ b/mcl/tests/poly.rs @@ -0,0 +1,155 @@ +// #[path = "./local_tests/local_poly.rs"] +// pub mod local_poly; + +#[cfg(test)] +mod tests { + use kzg_bench::tests::poly::{ + create_poly_of_length_ten, poly_div_by_zero, poly_div_fast_test, poly_div_long_test, + poly_div_random, poly_eval_0_check, poly_eval_check, poly_eval_nil_check, + poly_inverse_simple_0, poly_inverse_simple_1, poly_mul_direct_test, poly_mul_fft_test, + poly_mul_random, poly_test_div, + }; + use rust_kzg_mcl::types::fft_settings::MclFFTSettings; + use rust_kzg_mcl::types::fr::MclFr; + use rust_kzg_mcl::types::poly::MclPoly; + + // Local tests + // #[test] + // fn local_create_poly_of_length_ten_() { + // create_poly_of_length_ten() + // } + // + // #[test] + // fn local_poly_pad_works_rand_() { + // poly_pad_works_rand() + // } + // + // #[test] + // fn local_poly_eval_check_() { + // poly_eval_check() + // } + // + // #[test] + // fn local_poly_eval_0_check_() { poly_eval_0_check() } + // + // #[test] + // fn local_poly_eval_nil_check_() { + // poly_eval_nil_check() + // } + // + // #[test] + // fn local_poly_inverse_simple_0_() { + // poly_inverse_simple_0() + // } + // + // #[test] + // fn local_poly_inverse_simple_1_() { + // poly_inverse_simple_1() + // } + // + // #[test] + // fn local_test_poly_div_by_zero_() { + // test_poly_div_by_zero() + // } + // + // #[test] + // fn local_poly_div_long_test_() { + // poly_div_long_test() + // } + // + // #[test] + // fn local_poly_div_fast_test_() { + // poly_div_fast_test() + // } + // + // #[test] + // fn local_poly_mul_direct_test_() { + // poly_mul_direct_test() + // } + // + // #[test] + // fn local_poly_mul_fft_test_() { + // poly_mul_fft_test() + // } + // + // #[test] + // fn local_poly_mul_random_() { + // poly_mul_random() + // } + // + // #[test] + // fn local_poly_div_random_() { + // poly_div_random() + // } + + // Shared tests + #[test] + fn create_poly_of_length_ten_() { + create_poly_of_length_ten::() + } + + #[test] + fn poly_eval_check_() { + poly_eval_check::() + } + + #[test] + fn poly_eval_0_check_() { + poly_eval_0_check::() + } + + #[test] + fn poly_eval_nil_check_() { + poly_eval_nil_check::() + } + + #[test] + fn poly_inverse_simple_0_() { + poly_inverse_simple_0::() + } + + #[test] + fn poly_inverse_simple_1_() { + poly_inverse_simple_1::() + } + + #[test] + fn poly_test_div_() { + poly_test_div::() + } + + #[test] + fn poly_div_by_zero_() { + poly_div_by_zero::() + } + + #[test] + fn poly_mul_direct_test_() { + poly_mul_direct_test::() + } + + #[test] + fn poly_mul_fft_test_() { + poly_mul_fft_test::() + } + + #[test] + fn poly_mul_random_() { + poly_mul_random::() + } + + #[test] + fn poly_div_random_() { + poly_div_random::() + } + + #[test] + fn poly_div_long_test_() { + poly_div_long_test::() + } + + #[test] + fn poly_div_fast_test_() { + poly_div_fast_test::() + } +} diff --git a/mcl/tests/recovery.rs b/mcl/tests/recovery.rs new file mode 100644 index 000000000..9fe88d668 --- /dev/null +++ b/mcl/tests/recovery.rs @@ -0,0 +1,29 @@ +// #[path = "./local_tests/local_recovery.rs"] +// pub mod local_recovery; + +#[cfg(test)] +mod tests { + use kzg_bench::tests::recover::*; + // uncomment to use the local tests + //use crate::local_recovery::{recover_random, recover_simple}; + + use rust_kzg_mcl::types::fft_settings::MclFFTSettings; + use rust_kzg_mcl::types::fr::MclFr; + use rust_kzg_mcl::types::poly::MclPoly; + + // Shared tests + #[test] + fn recover_simple_() { + recover_simple::(); + } + + #[test] + fn recover_random_() { + recover_random::(); + } + + #[test] + fn more_than_half_missing_() { + more_than_half_missing::(); + } +} diff --git a/mcl/tests/zero_poly.rs b/mcl/tests/zero_poly.rs new file mode 100644 index 000000000..4a8d38bf4 --- /dev/null +++ b/mcl/tests/zero_poly.rs @@ -0,0 +1,45 @@ +#[cfg(test)] +mod tests { + use kzg_bench::tests::zero_poly::{ + check_test_data, reduce_partials_random, test_reduce_partials, zero_poly_252, + zero_poly_all_but_one, zero_poly_known, zero_poly_random, + }; + use rust_kzg_mcl::types::fft_settings::MclFFTSettings; + use rust_kzg_mcl::types::fr::MclFr; + use rust_kzg_mcl::types::poly::MclPoly; + + #[test] + fn test_reduce_partials_() { + test_reduce_partials::(); + } + + #[test] + fn reduce_partials_random_() { + reduce_partials_random::(); + } + + #[test] + fn check_test_data_() { + check_test_data::(); + } + + #[test] + fn zero_poly_known_() { + zero_poly_known::(); + } + + #[test] + fn zero_poly_random_() { + zero_poly_random::(); + } + + #[test] + fn zero_poly_all_but_one_() { + zero_poly_all_but_one::(); + } + + #[test] + fn zero_poly_252_() { + zero_poly_252::(); + } +}