From 48f6a8bbf6112e983823c7ecee252f5d8872d881 Mon Sep 17 00:00:00 2001 From: Andenis Date: Sun, 13 Oct 2024 12:37:09 +0300 Subject: [PATCH 01/21] add arkwors3 eip_7594.rs file --- arkworks3/src/eip_7594.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 arkworks3/src/eip_7594.rs diff --git a/arkworks3/src/eip_7594.rs b/arkworks3/src/eip_7594.rs new file mode 100644 index 000000000..e69de29bb From 3a6d507ed568027977f26f50cf184920d1e606ea Mon Sep 17 00:00:00 2001 From: Andenis Date: Mon, 14 Oct 2024 00:55:05 +0300 Subject: [PATCH 02/21] Implement eip_7594 function types in arkworks3 crate --- arkworks3/src/eip_7594.rs | 38 ++++++++++++++++++++++++++++++++++++++ arkworks3/src/lib.rs | 1 + 2 files changed, 39 insertions(+) diff --git a/arkworks3/src/eip_7594.rs b/arkworks3/src/eip_7594.rs index e69de29bb..8d056f455 100644 --- a/arkworks3/src/eip_7594.rs +++ b/arkworks3/src/eip_7594.rs @@ -0,0 +1,38 @@ +use kzg::eip_4844::FIELD_ELEMENTS_PER_CELL; + +use crate::kzg_types::{ArkFr, ArkG1, ArkKZGSettings}; + +pub fn compute_cells_and_kzg_proofs_rust( + cells: Option<&mut [[ArkFr; FIELD_ELEMENTS_PER_CELL]]>, + proofs: Option<&mut [ArkG1]>, + blob: &[ArkFr], + s: &ArkKZGSettings, +) -> Result<(), String> { + kzg::eip_7594::compute_cells_and_kzg_proofs(cells, proofs, blob, s) +} + +pub fn recover_cells_and_kzg_proofs_rust( + recovered_cells: &mut [[ArkFr; FIELD_ELEMENTS_PER_CELL]], + recovered_proofs: Option<&mut [ArkG1]>, + cell_indicies: &[usize], + cells: &[[ArkFr; FIELD_ELEMENTS_PER_CELL]], + s: &ArkKZGSettings, +) -> Result<(), String> { + kzg::eip_7594::recover_cells_and_kzg_proofs( + recovered_cells, + recovered_proofs, + cell_indicies, + cells, + s, + ) +} + +pub fn verify_cell_kzg_proof_batch_rust( + commitments: &[ArkG1], + cell_indices: &[usize], + cells: &[[ArkFr; FIELD_ELEMENTS_PER_CELL]], + proofs: &[ArkG1], + s: &ArkKZGSettings, +) -> Result { + kzg::eip_7594::verify_cell_kzg_proof_batch(commitments, cell_indices, cells, proofs, s) +} \ No newline at end of file diff --git a/arkworks3/src/lib.rs b/arkworks3/src/lib.rs index 3681c1331..7d29aaa38 100644 --- a/arkworks3/src/lib.rs +++ b/arkworks3/src/lib.rs @@ -13,6 +13,7 @@ pub type Uniq = blst::blst_uniq; pub mod consts; pub mod das; pub mod eip_4844; +pub mod eip_7594; pub mod fft; pub mod fft_g1; pub mod fk20_proofs; From d0bf4fc084a61a56e9a4b2f43c038ca4ca9c3ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Mon, 14 Oct 2024 03:59:56 +0300 Subject: [PATCH 03/21] implemented new names matching blst in arkworks3 (everything except eip files) --- arkworks3/src/das.rs | 4 +- arkworks3/src/eip_7594.rs | 251 ++++++++++++++++++++++++++++++++++- arkworks3/src/fft.rs | 2 +- arkworks3/src/fft_g1.rs | 2 +- arkworks3/src/fk20_proofs.rs | 4 +- arkworks3/src/kzg_proofs.rs | 10 +- arkworks3/src/kzg_types.rs | 102 +++++++++----- arkworks3/src/zero_poly.rs | 4 +- 8 files changed, 331 insertions(+), 48 deletions(-) diff --git a/arkworks3/src/das.rs b/arkworks3/src/das.rs index 9754cacad..6adc8c06e 100644 --- a/arkworks3/src/das.rs +++ b/arkworks3/src/das.rs @@ -39,7 +39,7 @@ impl FFTSettings { for i in 0..halfhalf { let x = ab[i]; let y = ab[halfhalf + i]; - let y_times_root = y.mul(&self.expanded_roots_of_unity[(1 + 2 * i) * stride]); + let y_times_root = y.mul(&self.brp_roots_of_unity[(1 + 2 * i) * stride]); ab[i] = x.add(&y_times_root); ab[halfhalf + i] = x.sub(&y_times_root); } @@ -47,7 +47,7 @@ impl FFTSettings { Ordering::Equal => { let x = ab[0].add(&ab[1]); let y = ab[0].sub(&ab[1]); - let tmp = y.mul(&self.expanded_roots_of_unity[stride]); + let tmp = y.mul(&self.brp_roots_of_unity[stride]); ab[0] = x.add(&tmp); ab[1] = x.sub(&tmp); diff --git a/arkworks3/src/eip_7594.rs b/arkworks3/src/eip_7594.rs index 8d056f455..9826a19b4 100644 --- a/arkworks3/src/eip_7594.rs +++ b/arkworks3/src/eip_7594.rs @@ -1,12 +1,21 @@ -use kzg::eip_4844::FIELD_ELEMENTS_PER_CELL; +use kzg::{ + eip_4844::{ + Blob, Bytes48, CKZGSettings, Cell, KZGProof, BYTES_PER_FIELD_ELEMENT, CELLS_PER_EXT_BLOB, + C_KZG_RET, C_KZG_RET_BADARGS, C_KZG_RET_OK, FIELD_ELEMENTS_PER_CELL, + }, + // Fr, G1, +}; -use crate::kzg_types::{ArkFr, ArkG1, ArkKZGSettings}; +use crate::{ + types::{fr::ArkFr, g1::ArkG1, kzg_settings::LKZGSettings}, + utils::{deserialize_blob, kzg_settings_to_rust}, +}; pub fn compute_cells_and_kzg_proofs_rust( cells: Option<&mut [[ArkFr; FIELD_ELEMENTS_PER_CELL]]>, proofs: Option<&mut [ArkG1]>, blob: &[ArkFr], - s: &ArkKZGSettings, + s: &LKZGSettings, ) -> Result<(), String> { kzg::eip_7594::compute_cells_and_kzg_proofs(cells, proofs, blob, s) } @@ -16,7 +25,7 @@ pub fn recover_cells_and_kzg_proofs_rust( recovered_proofs: Option<&mut [ArkG1]>, cell_indicies: &[usize], cells: &[[ArkFr; FIELD_ELEMENTS_PER_CELL]], - s: &ArkKZGSettings, + s: &LKZGSettings, ) -> Result<(), String> { kzg::eip_7594::recover_cells_and_kzg_proofs( recovered_cells, @@ -32,7 +41,237 @@ pub fn verify_cell_kzg_proof_batch_rust( cell_indices: &[usize], cells: &[[ArkFr; FIELD_ELEMENTS_PER_CELL]], proofs: &[ArkG1], - s: &ArkKZGSettings, + s: &LKZGSettings, ) -> Result { kzg::eip_7594::verify_cell_kzg_proof_batch(commitments, cell_indices, cells, proofs, s) -} \ No newline at end of file +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn compute_cells_and_kzg_proofs( + cells: *mut Cell, + proofs: *mut KZGProof, + blob: *const Blob, + settings: *const CKZGSettings, +) -> C_KZG_RET { + unsafe fn inner( + cells: *mut Cell, + proofs: *mut KZGProof, + blob: *const Blob, + settings: *const CKZGSettings, + ) -> Result<(), String> { + let mut cells_rs = if cells.is_null() { + None + } else { + Some(vec![ + [ArkFr::default(); FIELD_ELEMENTS_PER_CELL]; + CELLS_PER_EXT_BLOB + ]) + }; + let mut proofs_rs = if proofs.is_null() { + None + } else { + Some(vec![ArkG1::default(); CELLS_PER_EXT_BLOB]) + }; + + let blob = deserialize_blob(blob).map_err(|_| "Invalid blob".to_string())?; + let settings = kzg_settings_to_rust(&*settings)?; + + compute_cells_and_kzg_proofs_rust( + cells_rs.as_deref_mut(), + proofs_rs.as_deref_mut(), + &blob, + &settings, + )?; + + if let Some(cells_rs) = cells_rs { + let cells = core::slice::from_raw_parts_mut(cells, CELLS_PER_EXT_BLOB); + for (cell_index, cell) in cells_rs.iter().enumerate() { + for (fr_index, fr) in cell.iter().enumerate() { + cells[cell_index].bytes[(fr_index * BYTES_PER_FIELD_ELEMENT) + ..((fr_index + 1) * BYTES_PER_FIELD_ELEMENT)] + .copy_from_slice(&fr.to_bytes()); + } + } + } + + if let Some(proofs_rs) = proofs_rs { + let proofs = core::slice::from_raw_parts_mut(proofs, CELLS_PER_EXT_BLOB); + for (proof_index, proof) in proofs_rs.iter().enumerate() { + proofs[proof_index].bytes.copy_from_slice(&proof.to_bytes()); + } + } + + Ok(()) + } + + match inner(cells, proofs, blob, settings) { + Ok(()) => C_KZG_RET_OK, + Err(_) => C_KZG_RET_BADARGS, + } +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn recover_cells_and_kzg_proofs( + recovered_cells: *mut Cell, + recovered_proofs: *mut KZGProof, + cell_indices: *const u64, + cells: *const Cell, + num_cells: u64, + s: *const CKZGSettings, +) -> C_KZG_RET { + unsafe fn inner( + recovered_cells: *mut Cell, + recovered_proofs: *mut KZGProof, + cell_indices: *const u64, + cells: *const Cell, + num_cells: u64, + s: *const CKZGSettings, + ) -> Result<(), String> { + let mut recovered_cells_rs = + vec![[ArkFr::default(); FIELD_ELEMENTS_PER_CELL]; CELLS_PER_EXT_BLOB]; + + let mut recovered_proofs_rs = if recovered_proofs.is_null() { + None + } else { + Some(vec![ArkG1::default(); CELLS_PER_EXT_BLOB]) + }; + + let cell_indicies = core::slice::from_raw_parts(cell_indices, num_cells as usize) + .iter() + .map(|it| *it as usize) + .collect::>(); + let cells = core::slice::from_raw_parts(cells, num_cells as usize) + .iter() + .map(|it| -> Result<[ArkFr; FIELD_ELEMENTS_PER_CELL], String> { + it.bytes + .chunks(BYTES_PER_FIELD_ELEMENT) + .map(ArkFr::from_bytes) + .collect::, String>>() + .and_then(|frs| { + frs.try_into() + .map_err(|_| "Invalid field element count per cell".to_string()) + }) + }) + .collect::, String>>()?; + let settings = kzg_settings_to_rust(&*s)?; + + recover_cells_and_kzg_proofs_rust( + &mut recovered_cells_rs, + recovered_proofs_rs.as_deref_mut(), + &cell_indicies, + &cells, + &settings, + )?; + + let recovered_cells = core::slice::from_raw_parts_mut(recovered_cells, CELLS_PER_EXT_BLOB); + for (cell_c, cell_rs) in recovered_cells.iter_mut().zip(recovered_cells_rs.iter()) { + cell_c.bytes.copy_from_slice( + &cell_rs + .iter() + .flat_map(|fr| fr.to_bytes()) + .collect::>(), + ); + } + + if let Some(recovered_proofs_rs) = recovered_proofs_rs { + let recovered_proofs = + core::slice::from_raw_parts_mut(recovered_proofs, CELLS_PER_EXT_BLOB); + + for (proof_c, proof_rs) in recovered_proofs.iter_mut().zip(recovered_proofs_rs.iter()) { + proof_c.bytes = proof_rs.to_bytes(); + } + } + + Ok(()) + } + + match inner( + recovered_cells, + recovered_proofs, + cell_indices, + cells, + num_cells, + s, + ) { + Ok(()) => C_KZG_RET_OK, + Err(_) => C_KZG_RET_BADARGS, + } +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn verify_cell_kzg_proof_batch( + ok: *mut bool, + commitments_bytes: *const Bytes48, + cell_indices: *const u64, + cells: *const Cell, + proofs_bytes: *const Bytes48, + num_cells: u64, + s: *const CKZGSettings, +) -> C_KZG_RET { + unsafe fn inner( + ok: *mut bool, + commitments_bytes: *const Bytes48, + cell_indices: *const u64, + cells: *const Cell, + proofs_bytes: *const Bytes48, + num_cells: u64, + s: *const CKZGSettings, + ) -> Result<(), String> { + let commitments = core::slice::from_raw_parts(commitments_bytes, num_cells as usize) + .iter() + .map(|bytes| ArkG1::from_bytes(&bytes.bytes)) + .collect::, String>>()?; + + let cell_indices = core::slice::from_raw_parts(cell_indices, num_cells as usize) + .iter() + .map(|it| *it as usize) + .collect::>(); + + let cells = core::slice::from_raw_parts(cells, num_cells as usize) + .iter() + .map(|it| -> Result<[ArkFr; FIELD_ELEMENTS_PER_CELL], String> { + it.bytes + .chunks(BYTES_PER_FIELD_ELEMENT) + .map(ArkFr::from_bytes) + .collect::, String>>() + .and_then(|frs| { + frs.try_into() + .map_err(|_| "Invalid field element count per cell".to_string()) + }) + }) + .collect::, String>>()?; + + let proofs = core::slice::from_raw_parts(proofs_bytes, num_cells as usize) + .iter() + .map(|bytes| ArkG1::from_bytes(&bytes.bytes)) + .collect::, String>>()?; + + let settings = kzg_settings_to_rust(&*s)?; + + *ok = verify_cell_kzg_proof_batch_rust( + &commitments, + &cell_indices, + &cells, + &proofs, + &settings, + )?; + + Ok(()) + } + + match inner( + ok, + commitments_bytes, + cell_indices, + cells, + proofs_bytes, + num_cells, + s, + ) { + Ok(()) => C_KZG_RET_OK, + Err(_) => C_KZG_RET_BADARGS, + } +} diff --git a/arkworks3/src/fft.rs b/arkworks3/src/fft.rs index 0ce1a9a23..d16a9f660 100644 --- a/arkworks3/src/fft.rs +++ b/arkworks3/src/fft.rs @@ -17,7 +17,7 @@ impl FFTFr for FFTSettings { let roots = if inverse { &self.reverse_roots_of_unity } else { - &self.expanded_roots_of_unity + &self.brp_roots_of_unity }; fft_fr_fast(&mut ret, data, 1, roots, stride); diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index 0292de7a6..6b916c8a3 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -145,7 +145,7 @@ impl FFTG1 for FFTSettings { let roots = if inverse { &self.reverse_roots_of_unity } else { - &self.expanded_roots_of_unity + &self.brp_roots_of_unity }; fft_g1_fast(&mut ret, data, 1, roots, stride, 1); diff --git a/arkworks3/src/fk20_proofs.rs b/arkworks3/src/fk20_proofs.rs index 5ea09a8ef..884c25fe1 100644 --- a/arkworks3/src/fk20_proofs.rs +++ b/arkworks3/src/fk20_proofs.rs @@ -45,7 +45,7 @@ impl let mut x = Vec::new(); for i in 0..(n - 1) { - x.push(ks.secret_g1[n - 2 - i]) + x.push(ks.g1_values_monomial[n - 2 - i]) } x.push(ArkG1::identity()); @@ -123,7 +123,7 @@ impl FK20MultiSettings= chunk_len { j -= chunk_len; } else { diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 5323fe202..0e9c2342e 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -15,11 +15,13 @@ use kzg::{Fr as FrTrait, G1, G2}; use kzg::{G1Mul, G2Mul}; use std::ops::Neg; +// use kzg::{FFTSettings, Fr, }; + #[derive(Debug, Clone)] pub struct FFTSettings { pub max_width: usize, pub root_of_unity: BlstFr, - pub expanded_roots_of_unity: Vec, + pub brp_roots_of_unity: Vec, pub reverse_roots_of_unity: Vec, pub roots_of_unity: Vec, } @@ -45,9 +47,11 @@ pub fn expand_root_of_unity(root: &BlstFr, width: usize) -> Result, #[derive(Debug, Clone, Default)] pub struct KZGSettings { pub fs: FFTSettings, - pub secret_g1: Vec, - pub secret_g2: Vec, + 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 fn generate_trusted_setup(len: usize, secret: [u8; 32usize]) -> (Vec, Vec) { diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 06737f23f..a59945f28 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -28,7 +28,7 @@ use blst::{ blst_p2_uncompress, BLST_ERROR, }; use kzg::common_utils::reverse_bit_order; -use kzg::eip_4844::{BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2}; +use kzg::eip_4844::{BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, FIELD_ELEMENTS_PER_BLOB, FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS}; use kzg::msm::precompute::{precompute, PrecomputationTable}; use kzg::{ FFTFr, FFTSettings, FFTSettingsPoly, Fr as KzgFr, G1Affine as G1AffineTrait, G1Fp, G1GetFp, @@ -783,7 +783,7 @@ impl Default for LFFTSettings { Self { max_width: 0, root_of_unity: ArkFr::zero(), - expanded_roots_of_unity: Vec::new(), + brp_roots_of_unity: Vec::new(), reverse_roots_of_unity: Vec::new(), roots_of_unity: Vec::new(), } @@ -801,18 +801,26 @@ impl FFTSettings for LFFTSettings { let max_width: usize = 1 << scale; let root_of_unity = ArkFr::from_u64_arr(&SCALE2_ROOT_OF_UNITY[scale]); - let expanded_roots_of_unity = expand_root_of_unity(&root_of_unity, max_width)?; - let mut reverse_roots_of_unity = expanded_roots_of_unity.clone(); + 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(); - let mut roots_of_unity = expanded_roots_of_unity.clone(); - roots_of_unity.pop(); - reverse_bit_order(&mut roots_of_unity)?; + // let expanded_roots_of_unity = expand_root_of_unity(&root_of_unity, max_width)?; + // let mut reverse_roots_of_unity = expanded_roots_of_unity.clone(); + // reverse_roots_of_unity.reverse(); + + // let mut roots_of_unity = expanded_roots_of_unity.clone(); + // roots_of_unity.pop(); + // reverse_bit_order(&mut roots_of_unity)?; Ok(LFFTSettings { max_width, root_of_unity, - expanded_roots_of_unity, + brp_roots_of_unity, reverse_roots_of_unity, roots_of_unity, }) @@ -822,12 +830,11 @@ impl FFTSettings for LFFTSettings { self.max_width } - fn get_expanded_roots_of_unity_at(&self, i: usize) -> ArkFr { - self.expanded_roots_of_unity[i] + fn get_brp_roots_of_unity(&self) -> &[ArkFr] { + &self.brp_roots_of_unity } - - fn get_expanded_roots_of_unity(&self) -> &[ArkFr] { - &self.expanded_roots_of_unity + fn get_brp_roots_of_unity_at(&self, i: usize) -> ArkFr { + self.brp_roots_of_unity[i] } fn get_reverse_roots_of_unity_at(&self, i: usize) -> ArkFr { @@ -849,15 +856,46 @@ impl FFTSettings for LFFTSettings { impl KZGSettings for LKZGSettings { fn new( - secret_g1: &[ArkG1], - secret_g2: &[ArkG2], - _length: usize, + g1_monomial: &[ArkG1], + g1_lagrange_brp: &[ArkG1], + g2_monomial: &[ArkG2], fft_settings: &LFFTSettings, ) -> Result { + if g1_monomial.len() != FIELD_ELEMENTS_PER_BLOB + || g1_lagrange_brp.len() != FIELD_ELEMENTS_PER_BLOB + || g2_monomial.len() != TRUSTED_SETUP_NUM_G2_POINTS + { + return Err("Length does not match FIELD_ELEMENTS_PER_BLOB".to_string()); + } + + let n = FIELD_ELEMENTS_PER_EXT_BLOB / 2; + let k = n / FIELD_ELEMENTS_PER_CELL; + let k2 = 2 * k; + + let mut points = vec![ArkG1::default(); k2]; + let mut x = vec![ArkG1::default(); k]; + let mut x_ext_fft_columns = vec![vec![ArkG1::default(); FIELD_ELEMENTS_PER_CELL]; k2]; + + for offset in 0..FIELD_ELEMENTS_PER_CELL { + let start = n - FIELD_ELEMENTS_PER_CELL - 1 - offset; + for (i, p) in x.iter_mut().enumerate().take(k - 1) { + let j = start - i * FIELD_ELEMENTS_PER_CELL; + *p = g1_monomial[j]; + } + x[k - 1] = ArkG1::identity(); + + // toeplitz_part_1(&mut points, &x, fft_settings)?; + + for row in 0..k2 { + x_ext_fft_columns[row][offset] = points[row]; + } + } Ok(Self { - secret_g1: secret_g1.to_vec(), - secret_g2: secret_g2.to_vec(), + 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: { #[cfg(feature = "sppark")] { @@ -892,21 +930,21 @@ impl KZGSettings Result { - if p.coeffs.len() > self.secret_g1.len() { + if p.coeffs.len() > self.g1_values_lagrange_brp.len() { return Err(String::from("Polynomial is longer than secret g1")); } let mut out = ArkG1::default(); g1_linear_combination( &mut out, - &self.secret_g1, + &self.g1_values_lagrange_brp, &p.coeffs, p.coeffs.len(), self.get_precomputation(), @@ -945,7 +983,7 @@ impl KZGSettings Result { let x_g2: ArkG2 = ArkG2::generator().mul(x); - let s_minus_x: ArkG2 = self.secret_g2[1].sub(&x_g2); + let s_minus_x: ArkG2 = self.g2_values_monomial[1].sub(&x_g2); let y_g1 = ArkG1::generator().mul(y); let commitment_minus_y: ArkG1 = com.sub(&y_g1); @@ -1023,7 +1061,7 @@ impl KZGSettings ArkFr { - self.fs.get_expanded_roots_of_unity_at(i) - } - fn get_roots_of_unity_at(&self, i: usize) -> ArkFr { self.fs.get_roots_of_unity_at(i) } @@ -1053,12 +1087,18 @@ impl KZGSettings &[ArkG1] { - &self.secret_g1 + fn get_g1_lagrange_brp(&self) -> &[ArkG1] { + &self.g1_values_lagrange_brp } - fn get_g2_secret(&self) -> &[ArkG2] { - &self.secret_g2 + fn get_g1_monomial(&self) -> &[ArkG1] { + &self.g1_values_monomial + } + fn get_g2_monomial(&self) -> &[ArkG2] { + &self.g2_values_monomial + } + fn get_x_ext_fft_column(&self, index: usize) -> &[ArkG1] { + &self.x_ext_fft_columns[index] } fn get_precomputation(&self) -> Option<&PrecomputationTable> { diff --git a/arkworks3/src/zero_poly.rs b/arkworks3/src/zero_poly.rs index 50619ef7e..c7b4d5159 100644 --- a/arkworks3/src/zero_poly.rs +++ b/arkworks3/src/zero_poly.rs @@ -33,10 +33,10 @@ impl ZeroPoly for FFTSettings { coeffs: vec![BlstFr::one(); indices.len() + 1], }; let mut poly = blst_poly_into_pc_poly(&blstpoly.coeffs); - poly.coeffs[0] = (self.expanded_roots_of_unity[indices[0] * stride]).fr.neg(); + poly.coeffs[0] = (self.brp_roots_of_unity[indices[0] * stride]).fr.neg(); for (i, indice) in indices.iter().enumerate().skip(1) { - let neg_di = (self.expanded_roots_of_unity[indice * stride]).fr.neg(); + let neg_di = (self.brp_roots_of_unity[indice * stride]).fr.neg(); poly.coeffs[i] = neg_di + poly.coeffs[i - 1]; From 1e0803cb9c2046579e550cad2c9d1be5fb663901 Mon Sep 17 00:00:00 2001 From: Andenis Date: Thu, 17 Oct 2024 16:12:58 +0300 Subject: [PATCH 04/21] Implement functions in utils, fix problems in eip_7594 --- arkworks3/src/eip_7594.rs | 5 +- arkworks3/src/kzg_types.rs | 2 +- arkworks3/src/utils.rs | 126 ++++++++++++++++++++++++++++++++++--- 3 files changed, 122 insertions(+), 11 deletions(-) diff --git a/arkworks3/src/eip_7594.rs b/arkworks3/src/eip_7594.rs index 9826a19b4..caa3b63ce 100644 --- a/arkworks3/src/eip_7594.rs +++ b/arkworks3/src/eip_7594.rs @@ -3,14 +3,15 @@ use kzg::{ Blob, Bytes48, CKZGSettings, Cell, KZGProof, BYTES_PER_FIELD_ELEMENT, CELLS_PER_EXT_BLOB, C_KZG_RET, C_KZG_RET_BADARGS, C_KZG_RET_OK, FIELD_ELEMENTS_PER_CELL, }, - // Fr, G1, + Fr, G1, }; use crate::{ - types::{fr::ArkFr, g1::ArkG1, kzg_settings::LKZGSettings}, + kzg_types::{ArkFr, ArkG1, LKZGSettings}, utils::{deserialize_blob, kzg_settings_to_rust}, }; + pub fn compute_cells_and_kzg_proofs_rust( cells: Option<&mut [[ArkFr; FIELD_ELEMENTS_PER_CELL]]>, proofs: Option<&mut [ArkG1]>, diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index a59945f28..52f85dc53 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -1,6 +1,6 @@ use crate::consts::SCALE2_ROOT_OF_UNITY; use crate::fft_g1::g1_linear_combination; -use crate::kzg_proofs::{ +pub use crate::kzg_proofs::{ eval_poly, expand_root_of_unity, pairings_verify, FFTSettings as LFFTSettings, KZGSettings as LKZGSettings, }; diff --git a/arkworks3/src/utils.rs b/arkworks3/src/utils.rs index 2efa82740..dee9889de 100644 --- a/arkworks3/src/utils.rs +++ b/arkworks3/src/utils.rs @@ -1,7 +1,17 @@ +use kzg::{ + eip_4844::{ + Blob, CKZGSettings, PrecomputationTableManager, BYTES_PER_FIELD_ELEMENT, + C_KZG_RET, C_KZG_RET_BADARGS, FIELD_ELEMENTS_PER_BLOB, FIELD_ELEMENTS_PER_CELL, + FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS, + }, + Fr, +}; + +use crate::kzg_types::{ArkFr, ArkG1, ArkG2, ArkFp, ArkG1Affine, LKZGSettings, LFFTSettings}; + use super::{Fp, P1}; -use crate::kzg_types::ArkFr; use crate::P2; -use ark_bls12_381::{g1, g2, Fq, Fq2, Fr}; +use ark_bls12_381::{g1, g2, Fq, Fq2, Fr as _Fr}; use ark_ec::models::short_weierstrass_jacobian::GroupProjective; use ark_ff::{BigInteger256, BigInteger384, Fp2}; use ark_poly::univariate::DensePolynomial as DensePoly; @@ -16,8 +26,108 @@ pub struct PolyData { pub coeffs: Vec, } // FIXME: Store just dense poly here + +pub(crate) 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); + if let Ok(result) = ArkFr::from_bytes(&bytes) { + Ok(result) + } else { + Err(C_KZG_RET_BADARGS) + } + }) + .collect::, C_KZG_RET>>() +} + +pub(crate) fn fft_settings_to_rust( + c_settings: *const CKZGSettings, +) -> Result { + let settings = unsafe { &*c_settings }; + + let roots_of_unity = unsafe { + core::slice::from_raw_parts(settings.roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB + 1) + .iter() + .map(|r| ArkFr::from_blst_fr(*r)) + .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| ArkFr::from_blst_fr(*r)) + .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| ArkFr::from_blst_fr(*r)) + .collect::>() + }; + + Ok(LFFTSettings { + 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, + }) +} + +pub(crate) static mut PRECOMPUTATION_TABLES: PrecomputationTableManager< + ArkFr, + ArkG1, + ArkFp, + ArkG1Affine, +> = PrecomputationTableManager::new(); + +pub(crate) fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result { + Ok(LKZGSettings { + fs: fft_settings_to_rust(c_settings)?, + g1_values_monomial: unsafe { + core::slice::from_raw_parts(c_settings.g1_values_monomial, FIELD_ELEMENTS_PER_BLOB) + } + .iter() + .map(|r| ArkG1::from_blst_p1(*r)) + .collect::>(), + g1_values_lagrange_brp: unsafe { + core::slice::from_raw_parts(c_settings.g1_values_lagrange_brp, FIELD_ELEMENTS_PER_BLOB) + } + .iter() + .map(|r| ArkG1::from_blst_p1(*r)) + .collect::>(), + g2_values_monomial: unsafe { + core::slice::from_raw_parts(c_settings.g2_values_monomial, TRUSTED_SETUP_NUM_G2_POINTS) + } + .iter() + .map(|r| ArkG2::from_blst_p2(*r)) + .collect::>(), + x_ext_fft_columns: unsafe { + core::slice::from_raw_parts( + c_settings.x_ext_fft_columns, + 2 * ((FIELD_ELEMENTS_PER_EXT_BLOB / 2) / FIELD_ELEMENTS_PER_CELL), + ) + } + .iter() + .map(|it| { + unsafe { core::slice::from_raw_parts(*it, FIELD_ELEMENTS_PER_CELL) } + .iter() + .map(|it| ArkG1::from_blst_p1(*it)) + .collect::>() + }) + .collect::>(), + precomputation: unsafe { PRECOMPUTATION_TABLES.get_precomputation(c_settings) }, + }) +} -pub fn pc_poly_into_blst_poly(poly: DensePoly) -> PolyData { +pub fn pc_poly_into_blst_poly(poly: DensePoly<_Fr>) -> PolyData { let mut bls_pol: Vec = { Vec::new() }; for x in poly.coeffs { bls_pol.push(ArkFr { fr: x }); @@ -25,8 +135,8 @@ pub fn pc_poly_into_blst_poly(poly: DensePoly) -> PolyData { PolyData { coeffs: bls_pol } } -pub fn blst_poly_into_pc_poly(pd: &[ArkFr]) -> DensePoly { - let mut poly: Vec = vec![Fr::default(); pd.len()]; +pub fn blst_poly_into_pc_poly(pd: &[ArkFr]) -> DensePoly<_Fr> { + let mut poly: Vec<_Fr> = vec![_Fr::default(); pd.len()]; for i in 0..pd.len() { poly[i] = pd[i].fr; } @@ -37,13 +147,13 @@ pub const fn pc_fq_into_blst_fp(fq: Fq) -> Fp { Fp { l: fq.0 .0 } } -pub const fn blst_fr_into_pc_fr(fr: blst_fr) -> Fr { +pub const fn blst_fr_into_pc_fr(fr: blst_fr) -> _Fr { let big_int = BigInteger256::new(fr.l); - Fr::new(big_int) + _Fr::new(big_int) } -pub const fn pc_fr_into_blst_fr(fr: Fr) -> blst_fr { +pub const fn pc_fr_into_blst_fr(fr: _Fr) -> blst_fr { blst::blst_fr { l: fr.0 .0 } } From e5ac2ede5cbfb9ee467bc61f571807cd17eba879 Mon Sep 17 00:00:00 2001 From: Andenis Date: Thu, 17 Oct 2024 18:07:33 +0300 Subject: [PATCH 05/21] Fix problems in eip_4844, add functions to utils --- arkworks3/src/eip_4844.rs | 306 ++++++++++++++++---------------------- arkworks3/src/utils.rs | 97 ++++++++++++ 2 files changed, 224 insertions(+), 179 deletions(-) diff --git a/arkworks3/src/eip_4844.rs b/arkworks3/src/eip_4844.rs index fb8c62284..7155b5ed6 100644 --- a/arkworks3/src/eip_4844.rs +++ b/arkworks3/src/eip_4844.rs @@ -1,19 +1,17 @@ extern crate alloc; -use crate::kzg_proofs::{FFTSettings, KZGSettings}; -use crate::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine, ArkG2}; -use blst::{blst_fr, blst_p1, blst_p2}; -use kzg::common_utils::reverse_bit_order; +use crate::kzg_types::{ArkFr, ArkG1}; +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, Blob, Bytes32, Bytes48, CKZGSettings, KZGCommitment, KZGProof, - PrecomputationTableManager, BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, C_KZG_RET, + verify_kzg_proof_rust, FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, + + Blob, Bytes32, Bytes48, CKZGSettings, KZGCommitment, KZGProof, BYTES_PER_G1, C_KZG_RET, C_KZG_RET_BADARGS, C_KZG_RET_OK, FIELD_ELEMENTS_PER_BLOB, TRUSTED_SETUP_NUM_G1_POINTS, TRUSTED_SETUP_NUM_G2_POINTS, }; use kzg::{cfg_into_iter, Fr, G1}; -use std::ptr::null_mut; #[cfg(feature = "std")] use libc::FILE; @@ -22,131 +20,29 @@ use std::fs::File; #[cfg(feature = "std")] use std::io::Read; +use crate::utils::{ + deserialize_blob, handle_ckzg_badargs, kzg_settings_to_c, kzg_settings_to_rust, + PRECOMPUTATION_TABLES, +}; + #[cfg(feature = "parallel")] use rayon::prelude::*; #[cfg(feature = "std")] use kzg::eip_4844::load_trusted_setup_string; -static mut PRECOMPUTATION_TABLES: PrecomputationTableManager = - PrecomputationTableManager::new(); - #[cfg(feature = "std")] -pub fn load_trusted_setup_filename_rust(filepath: &str) -> Result { +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_bytes, g2_bytes) = load_trusted_setup_string(&contents)?; - load_trusted_setup_rust(g1_bytes.as_slice(), g2_bytes.as_slice()) -} - -fn fft_settings_to_rust(c_settings: *const CKZGSettings) -> Result { - let settings = unsafe { &*c_settings }; - let roots_of_unity = unsafe { - core::slice::from_raw_parts(settings.roots_of_unity, settings.max_width as usize) - .iter() - .map(|r| ArkFr::from_blst_fr(*r)) - .collect::>() - }; - let mut expanded_roots_of_unity = roots_of_unity.clone(); - reverse_bit_order(&mut expanded_roots_of_unity)?; - expanded_roots_of_unity.push(ArkFr::one()); - let mut reverse_roots_of_unity = expanded_roots_of_unity.clone(); - reverse_roots_of_unity.reverse(); - - let mut first_root = expanded_roots_of_unity[1]; - let first_root_arr = [first_root; 1]; - first_root = first_root_arr[0]; - - Ok(FFTSettings { - max_width: settings.max_width as usize, - root_of_unity: first_root, - expanded_roots_of_unity, - reverse_roots_of_unity, - roots_of_unity, - }) -} - -fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result { - let secret_g1 = unsafe { - core::slice::from_raw_parts(c_settings.g1_values, TRUSTED_SETUP_NUM_G1_POINTS) - .iter() - .map(|r| ArkG1::from_blst_p1(*r)) - .collect::>() - }; - let secret_g2 = unsafe { - core::slice::from_raw_parts(c_settings.g2_values, TRUSTED_SETUP_NUM_G2_POINTS) - .iter() - .map(|r| ArkG2::from_blst_p2(*r)) - .collect::>() - }; - Ok(KZGSettings { - fs: fft_settings_to_rust(c_settings)?, - secret_g1, - secret_g2, - // TODO: - precomputation: None, - }) -} - -fn kzg_settings_to_c(rust_settings: &KZGSettings) -> CKZGSettings { - let g1_val = rust_settings - .secret_g1 - .iter() - .map(|r| r.to_blst_p1()) - .collect::>(); - let g1_val = Box::new(g1_val); - let g2_val = rust_settings - .secret_g2 - .iter() - .map(|r| r.to_blst_p2()) - .collect::>(); - let x = g2_val.into_boxed_slice(); - let stat_ref = Box::leak(x); - let v = Box::into_raw(g1_val); - - let roots_of_unity = Box::new( - rust_settings - .fs - .roots_of_unity - .iter() - .map(|r| r.to_blst_fr()) - .collect::>(), - ); - - CKZGSettings { - max_width: rust_settings.fs.max_width as u64, - roots_of_unity: unsafe { (*Box::into_raw(roots_of_unity)).as_mut_ptr() }, - g1_values: unsafe { (*v).as_mut_ptr() }, - g2_values: stat_ref.as_mut_ptr(), - } -} - -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); - if let Ok(result) = ArkFr::from_bytes(&bytes) { - Ok(result) - } else { - Err(C_KZG_RET_BADARGS) - } - }) - .collect::, C_KZG_RET>>() -} - -macro_rules! handle_ckzg_badargs { - ($x: expr) => { - match $x { - Ok(value) => value, - Err(_) => return C_KZG_RET_BADARGS, - } - }; + 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 @@ -173,22 +69,32 @@ pub unsafe extern "C" fn blob_to_kzg_commitment( #[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, + 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, ) -> C_KZG_RET { - let g1_bytes = core::slice::from_raw_parts(g1_bytes, n1 * BYTES_PER_G1); - let g2_bytes = core::slice::from_raw_parts(g2_bytes, n2 * BYTES_PER_G2); - TRUSTED_SETUP_NUM_G1_POINTS = g1_bytes.len() / BYTES_PER_G1; - let mut settings = handle_ckzg_badargs!(load_trusted_setup_rust(g1_bytes, g2_bytes)); + 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; - C_KZG_RET_OK } @@ -202,8 +108,9 @@ pub unsafe extern "C" fn load_trusted_setup_file( 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_bytes, g2_bytes) = handle_ckzg_badargs!(load_trusted_setup_string(&s)); - TRUSTED_SETUP_NUM_G1_POINTS = g1_bytes.len() / BYTES_PER_G1; + 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 @@ -211,8 +118,9 @@ pub unsafe extern "C" fn load_trusted_setup_file( return C_KZG_RET_BADARGS; } let mut settings = handle_ckzg_badargs!(load_trusted_setup_rust( - g1_bytes.as_slice(), - g2_bytes.as_slice() + &g1_monomial_bytes, + &g1_lagrange_bytes, + &g2_monomial_bytes )); let c_settings = kzg_settings_to_c(&settings); @@ -224,6 +132,31 @@ pub unsafe extern "C" fn load_trusted_setup_file( C_KZG_RET_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, +) -> C_KZG_RET { + let deserialized_blob = match deserialize_blob(blob) { + Ok(value) => value, + Err(err) => return err, + }; + + let commitment_g1 = handle_ckzg_badargs!(ArkG1::from_bytes(&(*commitment_bytes).bytes)); + let settings = handle_ckzg_badargs!(kzg_settings_to_rust(s)); + let proof = handle_ckzg_badargs!(compute_blob_kzg_proof_rust( + &deserialized_blob, + &commitment_g1, + &settings + )); + + (*out).bytes = proof.to_bytes(); + C_KZG_RET_OK +} + /// # Safety #[no_mangle] pub unsafe extern "C" fn free_trusted_setup(s: *mut CKZGSettings) { @@ -231,30 +164,70 @@ pub unsafe extern "C" fn free_trusted_setup(s: *mut CKZGSettings) { 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(); + } - let max_width = (*s).max_width as usize; - let roots = Box::from_raw(core::slice::from_raw_parts_mut( - (*s).roots_of_unity, - max_width, - )); - drop(roots); - (*s).roots_of_unity = 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(); + } - let g1 = Box::from_raw(core::slice::from_raw_parts_mut( - (*s).g1_values, - TRUSTED_SETUP_NUM_G1_POINTS, - )); - drop(g1); - (*s).g1_values = 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(); + } - let g2 = Box::from_raw(core::slice::from_raw_parts_mut( - (*s).g2_values, - TRUSTED_SETUP_NUM_G2_POINTS, - )); - drop(g2); - (*s).g2_values = null_mut(); - (*s).max_width = 0; + 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(); + } + + PRECOMPUTATION_TABLES.remove_precomputation(&*s); } /// # Safety @@ -364,31 +337,6 @@ pub unsafe extern "C" fn verify_blob_kzg_proof_batch( } } -/// # 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 { - let deserialized_blob = match deserialize_blob(blob) { - Ok(value) => value, - Err(err) => return err, - }; - - let commitment_g1 = handle_ckzg_badargs!(ArkG1::from_bytes(&(*commitment_bytes).bytes)); - let settings = handle_ckzg_badargs!(kzg_settings_to_rust(s)); - let proof = handle_ckzg_badargs!(compute_blob_kzg_proof_rust( - &deserialized_blob, - &commitment_g1, - &settings - )); - - (*out).bytes = proof.to_bytes(); - C_KZG_RET_OK -} - /// # Safety #[no_mangle] pub unsafe extern "C" fn compute_kzg_proof( diff --git a/arkworks3/src/utils.rs b/arkworks3/src/utils.rs index dee9889de..862a72c07 100644 --- a/arkworks3/src/utils.rs +++ b/arkworks3/src/utils.rs @@ -1,3 +1,7 @@ +extern crate alloc; + +use alloc::boxed::Box; + use kzg::{ eip_4844::{ Blob, CKZGSettings, PrecomputationTableManager, BYTES_PER_FIELD_ELEMENT, @@ -43,6 +47,17 @@ pub(crate) unsafe fn deserialize_blob(blob: *const Blob) -> Result, C .collect::, C_KZG_RET>>() } +macro_rules! handle_ckzg_badargs { + ($x: expr) => { + match $x { + Ok(value) => value, + Err(_) => return kzg::eip_4844::C_KZG_RET_BADARGS, + } + }; +} + +pub(crate) use handle_ckzg_badargs; + pub(crate) fn fft_settings_to_rust( c_settings: *const CKZGSettings, ) -> Result { @@ -127,6 +142,88 @@ pub(crate) fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result CKZGSettings { + CKZGSettings { + roots_of_unity: Box::leak( + rust_settings + .fs + .roots_of_unity + .iter() + .map(|r| r.to_blst_fr()) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + brp_roots_of_unity: Box::leak( + rust_settings + .fs + .brp_roots_of_unity + .iter() + .map(|r| r.to_blst_fr()) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + reverse_roots_of_unity: Box::leak( + rust_settings + .fs + .reverse_roots_of_unity + .iter() + .map(|r| r.to_blst_fr()) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + g1_values_monomial: Box::leak( + rust_settings + .g1_values_monomial + .iter() + .map(|r| r.to_blst_p1()) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + g1_values_lagrange_brp: Box::leak( + rust_settings + .g1_values_lagrange_brp + .iter() + .map(|r| r.to_blst_p1()) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + g2_values_monomial: Box::leak( + rust_settings + .g2_values_monomial + .iter() + .map(|r| r.to_blst_p2()) + .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(|it| it.to_blst_p1()) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr() + }) + .collect::>() + .into_boxed_slice(), + ) + .as_mut_ptr(), + tables: core::ptr::null_mut(), + wbits: 0, + scratch_size: 0, + } +} + pub fn pc_poly_into_blst_poly(poly: DensePoly<_Fr>) -> PolyData { let mut bls_pol: Vec = { Vec::new() }; for x in poly.coeffs { From cdc01f87e9a699102c1c05cf47e4c7de784175ab Mon Sep 17 00:00:00 2001 From: Andenis Date: Wed, 23 Oct 2024 00:26:23 +0300 Subject: [PATCH 06/21] Fix all problem messages --- arkworks3/src/kzg_proofs.rs | 27 +++++++++++++---------- arkworks3/src/kzg_types.rs | 28 ++++++++++++++++++++++-- arkworks3/tests/eip_7594.rs | 40 ++++++++++++++++++++++++++++++++++ arkworks3/tests/fk20_proofs.rs | 6 +++++ arkworks3/tests/kzg_proofs.rs | 6 +++++ 5 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 arkworks3/tests/eip_7594.rs diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 0e9c2342e..782f59ebb 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -4,6 +4,7 @@ extern crate alloc; use super::utils::{blst_poly_into_pc_poly, PolyData}; use crate::kzg_types::{ArkFp, ArkFr, ArkG1Affine}; use crate::kzg_types::{ArkFr as BlstFr, ArkG1, ArkG2}; +//use crate::consts::{G1_GENERATOR, G2_GENERATOR}; use alloc::sync::Arc; use ark_bls12_381::Bls12_381; use ark_ec::{PairingEngine, ProjectiveCurve}; @@ -11,8 +12,7 @@ use ark_poly::Polynomial; use ark_std::{vec, One}; use kzg::eip_4844::hash_to_bls_field; use kzg::msm::precompute::PrecomputationTable; -use kzg::{Fr as FrTrait, G1, G2}; -use kzg::{G1Mul, G2Mul}; +use kzg::{Fr, G1Mul, G2Mul}; use std::ops::Neg; // use kzg::{FFTSettings, Fr, }; @@ -54,21 +54,26 @@ pub struct KZGSettings { pub x_ext_fft_columns: Vec> } -pub fn generate_trusted_setup(len: usize, secret: [u8; 32usize]) -> (Vec, Vec) { - let s = hash_to_bls_field::(&secret); - let mut s_pow = ArkFr::one(); +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(len); - let mut s2 = Vec::with_capacity(len); + let mut s1: Vec = Vec::with_capacity(n); + let mut s2: Vec = Vec::with_capacity(n); + let mut s3: Vec = Vec::with_capacity(n); - for _ in 0..len { - s1.push(ArkG1::generator().mul(&s_pow)); - s2.push(ArkG2::generator().mul(&s_pow)); + for _ in 0..n { + s1.push(s1[0].mul(&s_pow)); + s2.push(s1[0]); // TODO: this should be lagrange form + s3.push(s3[0].mul(&s_pow)); s_pow = s_pow.mul(&s); } - (s1, s2) + (s1, s2, s3) } pub fn eval_poly(p: &PolyData, x: &BlstFr) -> BlstFr { diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 52f85dc53..acf23e2f8 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -1,5 +1,5 @@ use crate::consts::SCALE2_ROOT_OF_UNITY; -use crate::fft_g1::g1_linear_combination; +use crate::fft_g1::{g1_linear_combination, fft_g1_fast}; pub use crate::kzg_proofs::{ eval_poly, expand_root_of_unity, pairings_verify, FFTSettings as LFFTSettings, KZGSettings as LKZGSettings, @@ -854,6 +854,30 @@ impl FFTSettings for LFFTSettings { } } +fn g1_fft(output: &mut [ArkG1], input: &[ArkG1], s: &LFFTSettings) -> Result<(), String> { + /* Ensure the length is valid */ + if input.len() > FIELD_ELEMENTS_PER_EXT_BLOB || !input.len().is_power_of_two() { + return Err("Invalid input size".to_string()); + } + + let roots_stride = FIELD_ELEMENTS_PER_EXT_BLOB / input.len(); + fft_g1_fast(output, input, 1, &s.roots_of_unity, roots_stride, 1); + + Ok(()) +} + +fn toeplitz_part_1(output: &mut [ArkG1], x: &[ArkG1], s: &LFFTSettings) -> Result<(), String> { + let n = x.len(); + let n2 = n * 2; + let mut x_ext = vec![ArkG1::identity(); n2]; + + x_ext[..n].copy_from_slice(x); + + g1_fft(output, &x_ext, s)?; + + Ok(()) +} + impl KZGSettings for LKZGSettings { fn new( g1_monomial: &[ArkG1], @@ -884,7 +908,7 @@ impl KZGSettings(&generate_trusted_setup); } + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn test_fk_single_strided() { fk_single_strided::< @@ -38,6 +40,7 @@ mod tests { >(&generate_trusted_setup); } + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn test_fk_multi_settings() { fk_multi_settings::< @@ -53,6 +56,7 @@ mod tests { >(&generate_trusted_setup); } + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn test_fk_multi_chunk_len_1_512() { fk_multi_chunk_len_1_512::< @@ -68,6 +72,7 @@ mod tests { >(&generate_trusted_setup); } + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn test_fk_multi_chunk_len_16_512() { fk_multi_chunk_len_16_512::< @@ -83,6 +88,7 @@ mod tests { >(&generate_trusted_setup); } + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn test_fk_multi_chunk_len_16_16() { fk_multi_chunk_len_16_16::< diff --git a/arkworks3/tests/kzg_proofs.rs b/arkworks3/tests/kzg_proofs.rs index a31e5ce95..94686a1bf 100644 --- a/arkworks3/tests/kzg_proofs.rs +++ b/arkworks3/tests/kzg_proofs.rs @@ -7,12 +7,15 @@ mod tests { use rust_kzg_arkworks3::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine, ArkG2}; use rust_kzg_arkworks3::utils::PolyData; + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn proof_single_() { proof_single::( &generate_trusted_setup, ); } + + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn commit_to_nil_poly_() { commit_to_nil_poly::< @@ -26,6 +29,8 @@ mod tests { ArkG1Affine, >(&generate_trusted_setup); } + + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn commit_to_too_long_poly_() { commit_to_too_long_poly_returns_err::< @@ -40,6 +45,7 @@ mod tests { >(&generate_trusted_setup); } + #[ignore = "KZG settings loading doesn't support trusted setup sizes other than FIELD_ELEMENTS_PER_BLOB (4096 points)"] #[test] fn proof_multi_() { proof_multi::( From f49f5ddf12bdd0aa5a06a6c5601b9222574a612a Mon Sep 17 00:00:00 2001 From: Andenis Date: Wed, 23 Oct 2024 15:03:53 +0300 Subject: [PATCH 07/21] Modify generate_trusted_setup --- arkworks3/src/kzg_proofs.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 782f59ebb..5cbd33016 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -4,7 +4,6 @@ extern crate alloc; use super::utils::{blst_poly_into_pc_poly, PolyData}; use crate::kzg_types::{ArkFp, ArkFr, ArkG1Affine}; use crate::kzg_types::{ArkFr as BlstFr, ArkG1, ArkG2}; -//use crate::consts::{G1_GENERATOR, G2_GENERATOR}; use alloc::sync::Arc; use ark_bls12_381::Bls12_381; use ark_ec::{PairingEngine, ProjectiveCurve}; @@ -12,11 +11,9 @@ use ark_poly::Polynomial; use ark_std::{vec, One}; use kzg::eip_4844::hash_to_bls_field; use kzg::msm::precompute::PrecomputationTable; -use kzg::{Fr, G1Mul, G2Mul}; +use kzg::{Fr, G1Mul, G2Mul, G1, G2}; use std::ops::Neg; -// use kzg::{FFTSettings, Fr, }; - #[derive(Debug, Clone)] pub struct FFTSettings { pub max_width: usize, @@ -61,14 +58,14 @@ pub fn generate_trusted_setup( let s = hash_to_bls_field(&secret); let mut s_pow = Fr::one(); - let mut s1: Vec = Vec::with_capacity(n); - let mut s2: Vec = Vec::with_capacity(n); - let mut s3: Vec = Vec::with_capacity(n); + 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(s1[0].mul(&s_pow)); - s2.push(s1[0]); // TODO: this should be lagrange form - s3.push(s3[0].mul(&s_pow)); + s1.push(ArkG1::generator().mul(&s_pow)); + s2.push(ArkG1::generator()); // TODO: this should be lagrange form + s3.push(ArkG2::generator().mul(&s_pow)); s_pow = s_pow.mul(&s); } From 806998468ee2e0a6f3c1e43f8fe9f356810fac63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Sat, 26 Oct 2024 10:45:55 +0300 Subject: [PATCH 08/21] ran cargo frm --- arkworks3/src/eip_4844.rs | 7 +++---- arkworks3/src/eip_7594.rs | 1 - arkworks3/src/kzg_proofs.rs | 2 +- arkworks3/src/kzg_types.rs | 7 +++++-- arkworks3/src/utils.rs | 10 +++++----- arkworks3/tests/eip_7594.rs | 2 +- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/arkworks3/src/eip_4844.rs b/arkworks3/src/eip_4844.rs index 7155b5ed6..216dd0169 100644 --- a/arkworks3/src/eip_4844.rs +++ b/arkworks3/src/eip_4844.rs @@ -5,10 +5,9 @@ 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, FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, - - Blob, Bytes32, Bytes48, CKZGSettings, KZGCommitment, KZGProof, BYTES_PER_G1, C_KZG_RET, - C_KZG_RET_BADARGS, C_KZG_RET_OK, FIELD_ELEMENTS_PER_BLOB, TRUSTED_SETUP_NUM_G1_POINTS, + verify_kzg_proof_rust, Blob, Bytes32, Bytes48, CKZGSettings, KZGCommitment, KZGProof, + BYTES_PER_G1, C_KZG_RET, C_KZG_RET_BADARGS, C_KZG_RET_OK, FIELD_ELEMENTS_PER_BLOB, + FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G1_POINTS, TRUSTED_SETUP_NUM_G2_POINTS, }; use kzg::{cfg_into_iter, Fr, G1}; diff --git a/arkworks3/src/eip_7594.rs b/arkworks3/src/eip_7594.rs index caa3b63ce..eaca25478 100644 --- a/arkworks3/src/eip_7594.rs +++ b/arkworks3/src/eip_7594.rs @@ -11,7 +11,6 @@ use crate::{ utils::{deserialize_blob, kzg_settings_to_rust}, }; - pub fn compute_cells_and_kzg_proofs_rust( cells: Option<&mut [[ArkFr; FIELD_ELEMENTS_PER_CELL]]>, proofs: Option<&mut [ArkG1]>, diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 5cbd33016..0bac8c2a1 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -48,7 +48,7 @@ pub struct KZGSettings { pub g1_values_lagrange_brp: Vec, pub g2_values_monomial: Vec, pub precomputation: Option>>, - pub x_ext_fft_columns: Vec> + pub x_ext_fft_columns: Vec>, } pub fn generate_trusted_setup( diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index acf23e2f8..1c7668152 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -1,5 +1,5 @@ use crate::consts::SCALE2_ROOT_OF_UNITY; -use crate::fft_g1::{g1_linear_combination, fft_g1_fast}; +use crate::fft_g1::{fft_g1_fast, g1_linear_combination}; pub use crate::kzg_proofs::{ eval_poly, expand_root_of_unity, pairings_verify, FFTSettings as LFFTSettings, KZGSettings as LKZGSettings, @@ -28,7 +28,10 @@ use blst::{ blst_p2_uncompress, BLST_ERROR, }; use kzg::common_utils::reverse_bit_order; -use kzg::eip_4844::{BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, FIELD_ELEMENTS_PER_BLOB, FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS}; +use kzg::eip_4844::{ + BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, FIELD_ELEMENTS_PER_BLOB, + FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS, +}; use kzg::msm::precompute::{precompute, PrecomputationTable}; use kzg::{ FFTFr, FFTSettings, FFTSettingsPoly, Fr as KzgFr, G1Affine as G1AffineTrait, G1Fp, G1GetFp, diff --git a/arkworks3/src/utils.rs b/arkworks3/src/utils.rs index 862a72c07..2dab77124 100644 --- a/arkworks3/src/utils.rs +++ b/arkworks3/src/utils.rs @@ -4,14 +4,14 @@ use alloc::boxed::Box; use kzg::{ eip_4844::{ - Blob, CKZGSettings, PrecomputationTableManager, BYTES_PER_FIELD_ELEMENT, - C_KZG_RET, C_KZG_RET_BADARGS, FIELD_ELEMENTS_PER_BLOB, FIELD_ELEMENTS_PER_CELL, + Blob, CKZGSettings, PrecomputationTableManager, BYTES_PER_FIELD_ELEMENT, C_KZG_RET, + C_KZG_RET_BADARGS, FIELD_ELEMENTS_PER_BLOB, FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS, }, - Fr, + Fr, }; -use crate::kzg_types::{ArkFr, ArkG1, ArkG2, ArkFp, ArkG1Affine, LKZGSettings, LFFTSettings}; +use crate::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine, ArkG2, LFFTSettings, LKZGSettings}; use super::{Fp, P1}; use crate::P2; @@ -30,7 +30,7 @@ pub struct PolyData { pub coeffs: Vec, } // FIXME: Store just dense poly here - + pub(crate) unsafe fn deserialize_blob(blob: *const Blob) -> Result, C_KZG_RET> { (*blob) .bytes diff --git a/arkworks3/tests/eip_7594.rs b/arkworks3/tests/eip_7594.rs index 03b2bbc11..c9f7a8d4a 100644 --- a/arkworks3/tests/eip_7594.rs +++ b/arkworks3/tests/eip_7594.rs @@ -37,4 +37,4 @@ mod tests { &verify_cell_kzg_proof_batch_rust, ); } -} \ No newline at end of file +} From d7a4f759c62c5607910ba2a1cc9508d0c2261695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Sat, 26 Oct 2024 13:35:13 +0300 Subject: [PATCH 09/21] changed to use LFFTSettings and LKZGsettings --- arkworks3/src/das.rs | 6 ++-- arkworks3/src/fft.rs | 4 +-- arkworks3/src/fft_g1.rs | 4 +-- arkworks3/src/fk20_proofs.rs | 49 +++++++++++++++++++++----------- arkworks3/src/kzg_proofs.rs | 55 ++++++++++++++++++++++-------------- arkworks3/src/kzg_types.rs | 22 +++++++++++---- arkworks3/src/poly.rs | 10 +++---- arkworks3/src/recover.rs | 8 +++--- arkworks3/src/zero_poly.rs | 4 +-- 9 files changed, 102 insertions(+), 60 deletions(-) diff --git a/arkworks3/src/das.rs b/arkworks3/src/das.rs index 6adc8c06e..02425d095 100644 --- a/arkworks3/src/das.rs +++ b/arkworks3/src/das.rs @@ -1,9 +1,9 @@ -use crate::kzg_proofs::FFTSettings; +use crate::kzg_proofs::LFFTSettings; use crate::kzg_types::ArkFr as BlstFr; use kzg::{Fr, DAS}; use std::cmp::Ordering; -impl FFTSettings { +impl LFFTSettings { fn das_fft_extension_stride(&self, ab: &mut [BlstFr], stride: usize) { match ab.len().cmp(&2_usize) { Ordering::Less => {} @@ -56,7 +56,7 @@ impl FFTSettings { } } -impl DAS for FFTSettings { +impl DAS for LFFTSettings { fn das_fft_extension(&self, vals: &[BlstFr]) -> Result, String> { if vals.is_empty() { return Err(String::from("vals can not be empty")); diff --git a/arkworks3/src/fft.rs b/arkworks3/src/fft.rs index d16a9f660..77e36c494 100644 --- a/arkworks3/src/fft.rs +++ b/arkworks3/src/fft.rs @@ -1,8 +1,8 @@ -use crate::kzg_proofs::FFTSettings; +use crate::kzg_proofs::LFFTSettings; use crate::kzg_types::ArkFr as BlstFr; use kzg::{FFTFr, Fr as FFr}; -impl FFTFr for FFTSettings { +impl FFTFr for LFFTSettings { fn fft_fr(&self, data: &[BlstFr], inverse: bool) -> Result, String> { if data.len() > self.max_width { return Err(String::from("data length is longer than allowed max width")); diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index 6b916c8a3..6eb0df651 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -1,4 +1,4 @@ -use crate::kzg_proofs::FFTSettings; +use crate::kzg_proofs::LFFTSettings; use crate::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine}; use kzg::cfg_into_iter; @@ -130,7 +130,7 @@ pub fn make_data(data: usize) -> Vec { vec } -impl FFTG1 for FFTSettings { +impl FFTG1 for LFFTSettings { fn fft_g1(&self, data: &[ArkG1], inverse: bool) -> Result, String> { if data.len() > self.max_width { return Err(String::from("data length is longer than allowed max width")); diff --git a/arkworks3/src/fk20_proofs.rs b/arkworks3/src/fk20_proofs.rs index 884c25fe1..9d7676054 100644 --- a/arkworks3/src/fk20_proofs.rs +++ b/arkworks3/src/fk20_proofs.rs @@ -1,4 +1,4 @@ -use crate::kzg_proofs::{FFTSettings, KZGSettings}; +use crate::kzg_proofs::{LFFTSettings, LKZGSettings}; use crate::kzg_types::{ArkFp, ArkFr as BlstFr, ArkG1, ArkG1Affine, ArkG2}; use crate::utils::PolyData; use kzg::common_utils::reverse_bit_order; @@ -10,7 +10,7 @@ use rayon::prelude::*; #[repr(C)] #[derive(Debug, Clone, Default)] pub struct KzgFK20SingleSettings { - pub ks: KZGSettings, + pub ks: LKZGSettings, pub x_ext_fft: Vec, pub x_ext_fft_len: usize, } @@ -18,17 +18,25 @@ pub struct KzgFK20SingleSettings { #[repr(C)] #[derive(Debug, Clone, Default)] pub struct KzgFK20MultiSettings { - pub ks: KZGSettings, + pub ks: LKZGSettings, pub chunk_len: usize, pub x_ext_fft_files: Vec>, pub length: usize, } impl - FK20SingleSettings - for KzgFK20SingleSettings + FK20SingleSettings< + BlstFr, + ArkG1, + ArkG2, + LFFTSettings, + PolyData, + LKZGSettings, + ArkFp, + ArkG1Affine, + > for KzgFK20SingleSettings { - fn new(ks: &KZGSettings, n2: usize) -> Result { + fn new(ks: &LKZGSettings, n2: usize) -> Result { let n = n2 / 2; if n2 > ks.fs.max_width { @@ -49,9 +57,9 @@ impl } x.push(ArkG1::identity()); - let new_ks = KZGSettings { + let new_ks = LKZGSettings { fs: ks.fs.clone(), - ..KZGSettings::default() + ..LKZGSettings::default() }; Ok(KzgFK20SingleSettings { @@ -84,10 +92,19 @@ impl } } -impl FK20MultiSettings - for KzgFK20MultiSettings +impl + FK20MultiSettings< + BlstFr, + ArkG1, + ArkG2, + LFFTSettings, + PolyData, + LKZGSettings, + ArkFp, + ArkG1Affine, + > for KzgFK20MultiSettings { - fn new(ks: &KZGSettings, n2: usize, chunk_len: usize) -> Result { + fn new(ks: &LKZGSettings, n2: usize, chunk_len: usize) -> Result { if n2 > ks.fs.max_width { return Err(String::from( "n2 must be equal or less than kzg settings max width", @@ -134,9 +151,9 @@ impl FK20MultiSettings Result, String> { +fn toeplitz_part_1(x: &[ArkG1], fs: &LFFTSettings) -> Result, String> { let n = x.len(); let n2 = n * 2; @@ -290,7 +307,7 @@ fn toeplitz_part_1(x: &[ArkG1], fs: &FFTSettings) -> Result, String> fn toeplitz_part_2( toeplitz_coeffs: &PolyData, x_ext_fft: &[ArkG1], - fs: &FFTSettings, + fs: &LFFTSettings, ) -> Result, String> { let toeplitz_coeffs_fft = fs.fft_fr(&toeplitz_coeffs.coeffs, false).unwrap(); @@ -313,7 +330,7 @@ fn toeplitz_part_2( } } -fn toeplitz_part_3(h_ext_fft: &[ArkG1], fs: &FFTSettings) -> Result, String> { +fn toeplitz_part_3(h_ext_fft: &[ArkG1], fs: &LFFTSettings) -> Result, String> { let n = h_ext_fft.len() / 2; let mut out = fs.fft_g1(h_ext_fft, true).unwrap(); diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 0bac8c2a1..9f89d7512 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -1,7 +1,7 @@ #![allow(non_camel_case_types)] extern crate alloc; -use super::utils::{blst_poly_into_pc_poly, PolyData}; +use super::utils::PolyData; use crate::kzg_types::{ArkFp, ArkFr, ArkG1Affine}; use crate::kzg_types::{ArkFr as BlstFr, ArkG1, ArkG2}; use alloc::sync::Arc; @@ -9,13 +9,17 @@ use ark_bls12_381::Bls12_381; use ark_ec::{PairingEngine, ProjectiveCurve}; use ark_poly::Polynomial; use ark_std::{vec, One}; +use blst::{ + blst_fp12_is_one, blst_p1_affine, blst_p1_cneg, blst_p1_to_affine, blst_p2_affine, + blst_p2_to_affine, +}; use kzg::eip_4844::hash_to_bls_field; use kzg::msm::precompute::PrecomputationTable; use kzg::{Fr, G1Mul, G2Mul, G1, G2}; use std::ops::Neg; #[derive(Debug, Clone)] -pub struct FFTSettings { +pub struct LFFTSettings { pub max_width: usize, pub root_of_unity: BlstFr, pub brp_roots_of_unity: Vec, @@ -42,8 +46,8 @@ pub fn expand_root_of_unity(root: &BlstFr, width: usize) -> Result, } #[derive(Debug, Clone, Default)] -pub struct KZGSettings { - pub fs: FFTSettings, +pub struct LKZGSettings { + pub fs: LFFTSettings, pub g1_values_monomial: Vec, pub g1_values_lagrange_brp: Vec, pub g2_values_monomial: Vec, @@ -73,22 +77,31 @@ pub fn generate_trusted_setup( (s1, s2, s3) } -pub fn eval_poly(p: &PolyData, x: &BlstFr) -> BlstFr { - let poly = blst_poly_into_pc_poly(&p.coeffs); - BlstFr { - fr: poly.evaluate(&x.fr), - } -} - pub fn pairings_verify(a1: &ArkG1, a2: &ArkG2, b1: &ArkG1, b2: &ArkG2) -> bool { - let ark_a1_neg = a1.0.neg().into_affine(); - let ark_b1 = b1.0.into_affine(); - let ark_a2 = a2.0.into_affine(); - let ark_b2 = b2.0.into_affine(); - - Bls12_381::product_of_pairings(&[ - (ark_a1_neg.into(), ark_a2.into()), - (ark_b1.into(), ark_b2.into()), - ]) - .is_one() + // TODO: Should look into rewriting this without blst methods. Not sure if it is possible though. + let mut aa1 = blst_p1_affine::default(); + let mut bb1 = blst_p1_affine::default(); + + let mut aa2 = blst_p2_affine::default(); + let mut bb2 = blst_p2_affine::default(); + + // As an optimisation, we want to invert one of the pairings, + // so we negate one of the points. + let mut a1neg: ArkG1 = *a1; + unsafe { + blst_p1_cneg(&mut a1neg.0, true); + blst_p1_to_affine(&mut aa1, &a1neg.0); + + blst_p1_to_affine(&mut bb1, &b1.0); + blst_p2_to_affine(&mut aa2, &a2.0); + blst_p2_to_affine(&mut bb2, &b2.0); + + let dst = [0u8; 3]; + let mut pairing_blst = blst::Pairing::new(false, &dst); + pairing_blst.raw_aggregate(&aa2, &aa1); + pairing_blst.raw_aggregate(&bb2, &bb1); + let gt_point = pairing_blst.as_fp12().final_exp(); + + blst_fp12_is_one(>_point) + } } diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 1c7668152..9932c02ab 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -1,9 +1,6 @@ use crate::consts::SCALE2_ROOT_OF_UNITY; use crate::fft_g1::{fft_g1_fast, g1_linear_combination}; -pub use crate::kzg_proofs::{ - eval_poly, expand_root_of_unity, pairings_verify, FFTSettings as LFFTSettings, - KZGSettings as LKZGSettings, -}; +pub use crate::kzg_proofs::{expand_root_of_unity, pairings_verify, LFFTSettings, LKZGSettings}; use crate::poly::{poly_fast_div, poly_inverse, poly_long_div, poly_mul_direct, poly_mul_fft}; use crate::recover::{scale_poly, unscale_poly}; use crate::utils::{ @@ -734,7 +731,22 @@ impl Poly for PolyData { } fn eval(&self, x: &ArkFr) -> ArkFr { - eval_poly(self, x) + if self.coeffs.is_empty() { + return ArkFr::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) { diff --git a/arkworks3/src/poly.rs b/arkworks3/src/poly.rs index 01199a7d8..a85757169 100644 --- a/arkworks3/src/poly.rs +++ b/arkworks3/src/poly.rs @@ -1,4 +1,4 @@ -use super::kzg_proofs::FFTSettings; +use super::kzg_proofs::LFFTSettings; use super::utils::{blst_poly_into_pc_poly, PolyData}; use crate::kzg_types::ArkFr as BlstFr; use crate::utils::pc_poly_into_blst_poly; @@ -33,7 +33,7 @@ pub fn poly_inverse(b: &PolyData, output_len: usize) -> Result let maxd = output_len - 1; let scale = next_pow_of_2(log2_pow2(2 * output_len - 1)); - let fs = FFTSettings::new(scale).unwrap(); + let fs = LFFTSettings::new(scale).unwrap(); let mut tmp0: PolyData; let mut tmp1: PolyData; @@ -104,7 +104,7 @@ pub fn poly_long_div(p1: &PolyData, p2: &PolyData) -> Result { pub fn poly_mul( a: &PolyData, b: &PolyData, - fs: Option<&FFTSettings>, + fs: Option<&LFFTSettings>, len: usize, ) -> Result { if a.coeffs.len() < 64 || b.coeffs.len() < 64 || len < 128 { @@ -117,7 +117,7 @@ pub fn poly_mul( pub fn poly_mul_fft( a: &PolyData, b: &PolyData, - fs: Option<&FFTSettings>, + fs: Option<&LFFTSettings>, len: usize, ) -> Result { // Truncate a and b so as not to do excess work for the number of coefficients required. @@ -130,7 +130,7 @@ pub fn poly_mul_fft( x.clone() } else { let scale = log2_pow2(length); - FFTSettings::new(scale).unwrap() + LFFTSettings::new(scale).unwrap() }; if length > fs_p.max_width { 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/src/zero_poly.rs b/arkworks3/src/zero_poly.rs index c7b4d5159..dc4e7553f 100644 --- a/arkworks3/src/zero_poly.rs +++ b/arkworks3/src/zero_poly.rs @@ -1,4 +1,4 @@ -use super::kzg_proofs::FFTSettings; +use super::kzg_proofs::LFFTSettings; use super::utils::{blst_poly_into_pc_poly, pc_poly_into_blst_poly, PolyData}; use crate::kzg_types::ArkFr as BlstFr; use kzg::common_utils::next_pow_of_2; @@ -20,7 +20,7 @@ pub(crate) fn pad_poly(poly: &PolyData, new_length: usize) -> Result Ok(out) } -impl ZeroPoly for FFTSettings { +impl ZeroPoly for LFFTSettings { fn do_zero_poly_mul_partial( &self, indices: &[usize], From 8e4221342cd677ee64803c62728f44650d5f5b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Mon, 28 Oct 2024 01:37:18 +0200 Subject: [PATCH 10/21] fixed errors in kzg_types --- arkworks3/src/kzg_types.rs | 483 +++++++++++++++++++++++++------------ 1 file changed, 333 insertions(+), 150 deletions(-) diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 9932c02ab..2ffe25d78 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -19,15 +19,22 @@ use ark_std::{One, Zero}; #[cfg(feature = "rand")] use ark_std::UniformRand; +use blst::p1_affines; use blst::{ - blst_fp, blst_fp2, blst_fr, blst_p1, blst_p1_affine, blst_p1_compress, blst_p1_from_affine, - blst_p1_in_g1, blst_p1_uncompress, blst_p2, blst_p2_affine, blst_p2_from_affine, - blst_p2_uncompress, BLST_ERROR, + blst_bendian_from_scalar, blst_fp, blst_fp2, blst_fr, blst_fr_add, blst_fr_cneg, + blst_fr_eucl_inverse, blst_fr_from_scalar, blst_fr_from_uint64, blst_fr_inverse, blst_fr_mul, + blst_fr_sqr, blst_fr_sub, blst_p1, blst_p1_add, blst_p1_add_or_double, blst_p1_affine, + blst_p1_cneg, blst_p1_compress, blst_p1_double, blst_p1_from_affine, blst_p1_in_g1, + blst_p1_is_equal, blst_p1_is_inf, blst_p1_mult, blst_p1_uncompress, blst_p2, + blst_p2_add_or_double, blst_p2_affine, blst_p2_cneg, blst_p2_compress, blst_p2_double, + blst_p2_from_affine, blst_p2_is_equal, blst_p2_mult, blst_p2_uncompress, blst_scalar, + blst_scalar_fr_check, blst_scalar_from_bendian, blst_scalar_from_fr, blst_uint64_from_fr, + BLST_ERROR, }; -use kzg::common_utils::reverse_bit_order; +use kzg::common_utils::{log2_u64, log_2_byte, reverse_bit_order}; use kzg::eip_4844::{ BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, FIELD_ELEMENTS_PER_BLOB, - FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS, + FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS }; use kzg::msm::precompute::{precompute, PrecomputationTable}; use kzg::{ @@ -51,21 +58,10 @@ const BLS12_381_MOD_256: [u64; 4] = [ ]; #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] -pub struct ArkFr { - pub fr: Fr, -} - -impl ArkFr { - pub fn from_blst_fr(fr: blst_fr) -> Self { - Self { - fr: blst_fr_into_pc_fr(fr), - } - } +pub struct ArkFr(pub blst_fr); - pub fn to_blst_fr(&self) -> blst_fr { - pc_fr_into_blst_fr(self.fr) - } -} +// impl Fr for ArkFr { + fn bigint_check_mod_256(a: &[u64; 4]) -> bool { let (_, overflow) = a[0].overflowing_sub(BLS12_381_MOD_256[0]); @@ -77,29 +73,31 @@ fn bigint_check_mod_256(a: &[u64; 4]) -> bool { impl KzgFr for ArkFr { fn null() -> Self { - Self { - fr: Fr::new(BigInteger256::new([u64::MAX; 4])), - } + Self::from_u64_arr(&[u64::MAX, u64::MAX, u64::MAX, u64::MAX]) } fn zero() -> Self { - // Self::from_u64(0) - Self { fr: Fr::zero() } + Self::from_u64(0) } fn one() -> Self { - // let one = Fr::one(); - // // assert_eq!(one.0.0, [0, 1, 1, 1], "must be eq"); - // Self { fr: one } Self::from_u64(1) } #[cfg(feature = "rand")] fn rand() -> Self { - let mut rng = rand::thread_rng(); - Self { - fr: Fr::rand(&mut rng), + let val: [u64; 4] = [ + rand::random(), + rand::random(), + rand::random(), + rand::random(), + ]; + let mut ret = Self::default(); + unsafe { + blst_fr_from_uint64(&mut ret.0, val.as_ptr()); } + + ret } fn from_bytes(bytes: &[u8]) -> Result { @@ -113,19 +111,16 @@ impl KzgFr for ArkFr { ) }) .and_then(|bytes: &[u8; BYTES_PER_FIELD_ELEMENT]| { - let storage: [u64; 4] = [ - bytes_be_to_uint64(&bytes[24..32]), - bytes_be_to_uint64(&bytes[16..24]), - bytes_be_to_uint64(&bytes[8..16]), - bytes_be_to_uint64(&bytes[0..8]), - ]; - let big_int = BigInteger256::new(storage); - if !big_int.is_zero() && !bigint_check_mod_256(&big_int.0) { - return Err("Invalid scalar".to_string()); + let mut bls_scalar = blst_scalar::default(); + let mut fr = blst_fr::default(); + unsafe { + blst_scalar_from_bendian(&mut bls_scalar, bytes.as_ptr()); + if !blst_scalar_fr_check(&bls_scalar) { + return Err("Invalid scalar".to_string()); + } + blst_fr_from_scalar(&mut fr, &bls_scalar); } - Ok(Self { - fr: Fr::from(big_int), - }) + Ok(Self(fr)) }) } @@ -139,8 +134,14 @@ impl KzgFr for ArkFr { bytes.len() ) }) - .map(|bytes: &[u8; BYTES_PER_FIELD_ELEMENT]| Self { - fr: Fr::from_be_bytes_mod_order(bytes), + .map(|bytes: &[u8; BYTES_PER_FIELD_ELEMENT]| { + let mut bls_scalar = blst_scalar::default(); + let mut fr = blst_fr::default(); + unsafe { + blst_scalar_from_bendian(&mut bls_scalar, bytes.as_ptr()); + blst_fr_from_scalar(&mut fr, &bls_scalar); + } + Self(fr) }) } @@ -150,134 +151,200 @@ impl KzgFr for ArkFr { } fn from_u64_arr(u: &[u64; 4]) -> Self { - Self { - fr: Fr::from(BigInteger256::new(*u)), + let mut ret = Self::default(); + unsafe { + blst_fr_from_uint64(&mut ret.0, u.as_ptr()); } + + ret } fn from_u64(val: u64) -> Self { - Self { fr: Fr::from(val) } + Self::from_u64_arr(&[val, 0, 0, 0]) } fn to_bytes(&self) -> [u8; 32] { - let big_int_256: BigInteger256 = Fr::into(self.fr); - <[u8; 32]>::try_from(big_int_256.to_bytes_be()).unwrap() + let mut scalar = blst_scalar::default(); + let mut bytes = [0u8; 32]; + unsafe { + blst_scalar_from_fr(&mut scalar, &self.0); + blst_bendian_from_scalar(bytes.as_mut_ptr(), &scalar); + } + + bytes } fn to_u64_arr(&self) -> [u64; 4] { - let b: BigInteger256 = Fr::into(self.fr); - b.0 + let mut val: [u64; 4] = [0; 4]; + unsafe { + blst_uint64_from_fr(val.as_mut_ptr(), &self.0); + } + + val } fn is_one(&self) -> bool { - self.fr.is_one() + let mut val: [u64; 4] = [0; 4]; + unsafe { + blst_uint64_from_fr(val.as_mut_ptr(), &self.0); + } + + val[0] == 1 && val[1] == 0 && val[2] == 0 && val[3] == 0 } fn is_zero(&self) -> bool { - self.fr.is_zero() + let mut val: [u64; 4] = [0; 4]; + unsafe { + blst_uint64_from_fr(val.as_mut_ptr(), &self.0); + } + + val[0] == 0 && val[1] == 0 && val[2] == 0 && val[3] == 0 } fn is_null(&self) -> bool { - self.equals(&ArkFr::null()) + self.equals(&Self::null()) } fn sqr(&self) -> Self { - Self { - fr: self.fr.square(), + let mut ret = Self::default(); + unsafe { + blst_fr_sqr(&mut ret.0, &self.0); } + + ret } fn mul(&self, b: &Self) -> Self { - Self { fr: self.fr * b.fr } + let mut ret = Self::default(); + unsafe { + blst_fr_mul(&mut ret.0, &self.0, &b.0); + } + + ret } fn add(&self, b: &Self) -> Self { - Self { fr: self.fr + b.fr } + let mut ret = Self::default(); + unsafe { + blst_fr_add(&mut ret.0, &self.0, &b.0); + } + + ret } fn sub(&self, b: &Self) -> Self { - Self { fr: self.fr - b.fr } + let mut ret = Self::default(); + unsafe { + blst_fr_sub(&mut ret.0, &self.0, &b.0); + } + + ret } fn eucl_inverse(&self) -> Self { // Inverse and eucl inverse work the same way - Self { - fr: self.fr.inverse().unwrap(), + let mut ret = Self::default(); + unsafe { + blst_fr_eucl_inverse(&mut ret.0, &self.0); } + + ret } fn negate(&self) -> Self { - Self { fr: self.fr.neg() } + let mut ret = Self::default(); + unsafe { + blst_fr_cneg(&mut ret.0, &self.0, true); + } + + ret } fn inverse(&self) -> Self { - Self { - fr: self.fr.inverse().unwrap(), + let mut ret = Self::default(); + unsafe { + blst_fr_inverse(&mut ret.0, &self.0); } + + ret } fn pow(&self, n: usize) -> Self { - Self { - fr: self.fr.pow([n as u64]), + 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 { - let div = self.fr / b.fr; - if div.0 .0.is_empty() { - Ok(Self { fr: Fr::zero() }) - } else { - Ok(Self { fr: div }) - } + let tmp = b.eucl_inverse(); + let out = self.mul(&tmp); + + Ok(out) } fn equals(&self, b: &Self) -> bool { - self.fr == b.fr + let mut val_a: [u64; 4] = [0; 4]; + let mut val_b: [u64; 4] = [0; 4]; + + unsafe { + blst_uint64_from_fr(val_a.as_mut_ptr(), &self.0); + blst_uint64_from_fr(val_b.as_mut_ptr(), &b.0); + } + + val_a[0] == val_b[0] && val_a[1] == val_b[1] && val_a[2] == val_b[2] && val_a[3] == val_b[3] } fn to_scalar(&self) -> Scalar256 { - Scalar256::from_u64(self.fr.0 .0) + let mut blst_scalar = blst_scalar::default(); + unsafe { + blst_scalar_from_fr(&mut blst_scalar, &self.0); + } + Scalar256::from_u8(&blst_scalar.b) } } #[repr(C)] #[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] -pub struct ArkG1(pub GroupProjective); +pub struct ArkG1(pub blst_p1); impl ArkG1 { - pub fn from_blst_p1(p1: blst_p1) -> Self { - Self(blst_p1_into_pc_g1projective(&p1)) - } - - pub fn to_blst_p1(&self) -> blst_p1 { - pc_g1projective_into_blst_p1(self.0) + pub(crate) const fn from_xyz(x: blst_fp, y: blst_fp, z: blst_fp) -> Self { + ArkG1(blst_p1 { x, y, z }) } } -impl From for ArkG1 { - fn from(p1: blst_p1) -> Self { - Self(blst_p1_into_pc_g1projective(&p1)) - } -} +// impl From for ArkG1 { +// fn from(p1: blst_p1) -> Self { +// Self(blst_p1_into_pc_g1projective(&p1)) +// } +// } impl G1 for ArkG1 { fn identity() -> Self { - ArkG1::from_blst_p1(blst_p1 { - x: blst_fp { - l: [0, 0, 0, 0, 0, 0], - }, - y: blst_fp { - l: [0, 0, 0, 0, 0, 0], - }, - z: blst_fp { - l: [0, 0, 0, 0, 0, 0], - }, - }) + ArkG1::from_xyz( + blst_fp { l: [0; 6] }, + blst_fp { l: [0; 6] }, + blst_fp { l: [0; 6] }, + ) } fn generator() -> Self { - ArkG1::from_blst_p1(blst_p1 { - x: blst_fp { + ArkG1::from_xyz( + blst_fp { l: [ 0x5cb38790fd530c16, 0x7817fc679976fff5, @@ -287,7 +354,7 @@ impl G1 for ArkG1 { 0x120177419e0bfb75, ], }, - y: blst_fp { + blst_fp { l: [ 0xbaac93d50ce72271, 0x8c22631a7918fd8e, @@ -297,7 +364,7 @@ impl G1 for ArkG1 { 0x0bbc3efc5008a26a, ], }, - z: blst_fp { + blst_fp { l: [ 0x760900000002fffd, 0xebf4000bc40c0002, @@ -307,12 +374,12 @@ impl G1 for ArkG1 { 0x15f65ec3fa80e493, ], }, - }) + ) } fn negative_generator() -> Self { - ArkG1::from_blst_p1(blst_p1 { - x: blst_fp { + ArkG1::from_xyz( + blst_fp { l: [ 0x5cb38790fd530c16, 0x7817fc679976fff5, @@ -322,7 +389,7 @@ impl G1 for ArkG1 { 0x120177419e0bfb75, ], }, - y: blst_fp { + blst_fp { l: [ 0xff526c2af318883a, 0x92899ce4383b0270, @@ -332,7 +399,7 @@ impl G1 for ArkG1 { 0x0e44d2ede9774430, ], }, - z: blst_fp { + blst_fp { l: [ 0x760900000002fffd, 0xebf4000bc40c0002, @@ -342,13 +409,44 @@ impl G1 for ArkG1 { 0x15f65ec3fa80e493, ], }, - }) + ) } #[cfg(feature = "rand")] fn rand() -> Self { - let mut rng = rand::thread_rng(); - Self(GroupProjective::rand(&mut rng)) + let result = ArkG1::from_xyz( + blst_fp { + l: [ + 0x5cb38790fd530c16, + 0x7817fc679976fff5, + 0x154f95c7143ba1c1, + 0xf0ae6acdf3d0e747, + 0xedce6ecc21dbf440, + 0x120177419e0bfb75, + ], + }, + blst_fp { + l: [ + 0xbaac93d50ce72271, + 0x8c22631a7918fd8e, + 0xdd595f13570725ce, + 0x51ac582950405194, + 0x0e1c8c3fad0059c0, + 0x0bbc3efc5008a26a, + ], + }, + blst_fp { + l: [ + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, + ], + }, + ); + result.mul(&kzg::Fr::rand()) } #[allow(clippy::bind_instead_of_map)] @@ -373,7 +471,7 @@ impl G1 for ArkG1 { let mut blst_point = blst_p1::default(); unsafe { blst_p1_from_affine(&mut blst_point, &blst_affine) }; - Ok(ArkG1::from_blst_p1(blst_point)) + Ok(ArkG1(blst_point)) }) } @@ -385,43 +483,63 @@ impl G1 for ArkG1 { fn to_bytes(&self) -> [u8; 48] { let mut out = [0u8; BYTES_PER_G1]; unsafe { - blst_p1_compress(out.as_mut_ptr(), &self.to_blst_p1()); + blst_p1_compress(out.as_mut_ptr(), &self.0); } out } fn add_or_dbl(&self, b: &Self) -> Self { - Self(self.0 + b.0) + let mut ret = Self::default(); + unsafe { + blst_p1_add_or_double(&mut ret.0, &self.0, &b.0); + } + ret } fn is_inf(&self) -> bool { - let temp = &self.0; - temp.z.is_zero() + unsafe { blst_p1_is_inf(&self.0) } } fn is_valid(&self) -> bool { - unsafe { blst_p1_in_g1(&self.to_blst_p1()) } + unsafe { + // The point must be on the right subgroup + blst_p1_in_g1(&self.0) + } } fn dbl(&self) -> Self { - Self(self.0.double()) + let mut result = blst_p1::default(); + unsafe { + blst_p1_double(&mut result, &self.0); + } + Self(result) } fn add(&self, b: &Self) -> Self { - Self(self.0 + b.0) + let mut ret = Self::default(); + unsafe { + blst_p1_add(&mut ret.0, &self.0, &b.0); + } + ret } fn sub(&self, b: &Self) -> Self { - Self(self.0.sub(&b.0)) + let mut b_negative: ArkG1 = *b; + let mut ret = Self::default(); + unsafe { + blst_p1_cneg(&mut b_negative.0, true); + blst_p1_add_or_double(&mut ret.0, &self.0, &b_negative.0); + ret + } } fn equals(&self, b: &Self) -> bool { - self.0.eq(&b.0) + unsafe { blst_p1_is_equal(&self.0, &b.0) } } fn zero() -> Self { - ArkG1::from_blst_p1(blst_p1 { - x: blst_fp { + ArkG1::from_xyz( + blst_fp { l: [ 8505329371266088957, 17002214543764226050, @@ -431,7 +549,7 @@ impl G1 for ArkG1 { 1582556514881692819, ], }, - y: blst_fp { + blst_fp { l: [ 8505329371266088957, 17002214543764226050, @@ -441,28 +559,65 @@ impl G1 for ArkG1 { 1582556514881692819, ], }, - z: blst_fp { + blst_fp { l: [0, 0, 0, 0, 0, 0], }, - }) + ) } fn add_or_dbl_assign(&mut self, b: &Self) { - self.0 += b.0; + unsafe { + blst::blst_p1_add_or_double(&mut self.0, &self.0, &b.0); + } } fn add_assign(&mut self, b: &Self) { - self.0.add_assign(b.0); + unsafe { + blst::blst_p1_add(&mut self.0, &self.0, &b.0); + } } fn dbl_assign(&mut self) { - self.0.double_in_place(); + unsafe { + blst::blst_p1_double(&mut self.0, &self.0); + } } } impl G1Mul for ArkG1 { fn mul(&self, b: &ArkFr) -> Self { - Self(self.0.mul(b.to_u64_arr())) + let mut scalar: blst_scalar = blst_scalar::default(); + unsafe { + blst_scalar_from_fr(&mut scalar, &b.0); + } + + // Count the number of bytes to be multiplied. + let mut i = scalar.b.len(); + while i != 0 && scalar.b[i - 1] == 0 { + i -= 1; + } + + let mut result = Self::default(); + if i == 0 { + return ArkG1::from_xyz( + blst_fp { l: [0; 6] }, + blst_fp { l: [0; 6] }, + blst_fp { l: [0; 6] }, + ); + } else if i == 1 && scalar.b[0] == 1 { + return *self; + } else { + // Count the number of bits to be multiplied. + unsafe { + blst_p1_mult( + &mut result.0, + &self.0, + &(scalar.b[0]), + 8 * i - 7 + log_2_byte(scalar.b[i - 1]), + ); + } + } + result } } @@ -1055,11 +1210,11 @@ impl KZGSettings for ArkG1 { #[repr(C)] #[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] -pub struct ArkG1Affine { - pub aff: G1Affine, -} +pub struct ArkG1Affine (pub blst_p1_affine); impl G1AffineTrait for ArkG1Affine { fn into_affine(g1: &ArkG1) -> Self { - Self { - aff: g1.0.into_affine(), + let mut ret: Self = Default::default(); + unsafe { + blst::blst_p1_to_affine(&mut ret.0, &g1.0); } + ret } fn into_affines(g1: &[ArkG1]) -> Vec { @@ -1291,47 +1446,75 @@ impl G1AffineTrait for ArkG1Affine { } fn to_proj(&self) -> ArkG1 { - ArkG1(self.aff.into_projective()) + let mut ret: ArkG1 = Default::default(); + unsafe { + blst::blst_p1_from_affine(&mut ret.0, &self.0); + } + ret } fn x(&self) -> &ArkFp { - unsafe { core::mem::transmute(&self.aff.x) } + unsafe { + // Transmute safe due to repr(C) on FsFp + core::mem::transmute(&self.0.x) + } } fn y(&self) -> &ArkFp { - unsafe { core::mem::transmute(&self.aff.y) } + unsafe { + // Transmute safe due to repr(C) on FsFp + core::mem::transmute(&self.0.y) + } } fn is_infinity(&self) -> bool { - self.aff.infinity + unsafe { blst::blst_p1_affine_is_inf(&self.0) } } - fn is_zero(&self) -> bool { - self.aff.is_zero() - } + // fn is_zero(&self) -> bool { + // self.aff.is_zero() + // } fn zero() -> Self { - Self { - aff: G1Affine::new(ArkFp::zero().0, ArkFp::zero().0, true), - } + Self(blst_p1_affine { + x: { + blst_fp { + l: [0, 0, 0, 0, 0, 0], + } + }, + y: { + blst_fp { + l: [0, 0, 0, 0, 0, 0], + } + }, + }) } - fn x_mut(&mut self) -> &mut ArkFp { - unsafe { core::mem::transmute(&mut self.aff.x) } + unsafe { + // Transmute safe due to repr(C) on FsFp + core::mem::transmute(&mut self.0.x) + } } fn y_mut(&mut self) -> &mut ArkFp { - unsafe { core::mem::transmute(&mut self.aff.y) } + unsafe { + // Transmute safe due to repr(C) on FsFp + core::mem::transmute(&mut self.0.y) + } } } pub struct ArkG1ProjAddAffine; impl G1ProjAddAffine for ArkG1ProjAddAffine { fn add_assign_affine(proj: &mut ArkG1, aff: &ArkG1Affine) { - proj.0.add_assign_mixed(&aff.aff); + unsafe { + blst::blst_p1_add_affine(&mut proj.0, &proj.0, &aff.0); + } } fn add_or_double_assign_affine(proj: &mut ArkG1, aff: &ArkG1Affine) { - proj.0.add_assign_mixed(&aff.aff); + unsafe { + blst::blst_p1_add_or_double_affine(&mut proj.0, &proj.0, &aff.0); + } } } From 574aae268b2f79e6d317dfe1ce40d39ccebf68b5 Mon Sep 17 00:00:00 2001 From: Andenis Date: Wed, 6 Nov 2024 21:18:50 +0200 Subject: [PATCH 11/21] Fix zero_poly.rs problems, update fft.rs --- Cargo.lock | 1 + arkworks3/Cargo.toml | 1 + arkworks3/src/fft.rs | 45 +++-- arkworks3/src/zero_poly.rs | 342 ++++++++++++++++++++++++------------- 4 files changed, 265 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 29faf3d5b..dfe841574 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1470,6 +1470,7 @@ dependencies = [ "rayon", "rust-kzg-arkworks3-sppark", "rust-kzg-arkworks3-sppark-wlc", + "smallvec", ] [[package]] diff --git a/arkworks3/Cargo.toml b/arkworks3/Cargo.toml index 4a7ce6bc1..050b51e54 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/src/fft.rs b/arkworks3/src/fft.rs index 77e36c494..bd89ef5cc 100644 --- a/arkworks3/src/fft.rs +++ b/arkworks3/src/fft.rs @@ -2,33 +2,58 @@ use crate::kzg_proofs::LFFTSettings; use crate::kzg_types::ArkFr as BlstFr; use kzg::{FFTFr, Fr as FFr}; -impl FFTFr for LFFTSettings { - fn fft_fr(&self, data: &[BlstFr], inverse: bool) -> Result, String> { +impl LFFTSettings { + /// Fast Fourier Transform for finite field elements, `output` must be zeroes + pub(crate) fn fft_fr_output( + &self, + data: &[BlstFr], + inverse: bool, + output: &mut [BlstFr], + ) -> Result<(), String> { if data.len() > self.max_width { - return Err(String::from("data length is longer than allowed 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("data length is not power of 2")); + 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(); - let mut ret = vec![BlstFr::default(); 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.brp_roots_of_unity + &self.roots_of_unity }; - fft_fr_fast(&mut ret, data, 1, roots, stride); + fft_fr_fast(output, data, 1, roots, stride); if inverse { let inv_fr_len = BlstFr::from_u64(data.len() as u64).inverse(); - ret[..data.len()] - .iter_mut() - .for_each(|f| *f = BlstFr::mul(f, &inv_fr_len)); + output.iter_mut().for_each(|f| *f = f.mul(&inv_fr_len)); } + Ok(()) + } +} + +impl FFTFr for LFFTSettings { + fn fft_fr(&self, data: &[BlstFr], inverse: bool) -> Result, String> { + let mut ret = vec![BlstFr::default(); data.len()]; + + self.fft_fr_output(data, inverse, &mut ret)?; + Ok(ret) } } diff --git a/arkworks3/src/zero_poly.rs b/arkworks3/src/zero_poly.rs index dc4e7553f..57fca2869 100644 --- a/arkworks3/src/zero_poly.rs +++ b/arkworks3/src/zero_poly.rs @@ -1,196 +1,310 @@ use super::kzg_proofs::LFFTSettings; -use super::utils::{blst_poly_into_pc_poly, pc_poly_into_blst_poly, PolyData}; +use super::utils::PolyData; use crate::kzg_types::ArkFr as BlstFr; use kzg::common_utils::next_pow_of_2; use kzg::{FFTFr, Fr as FrTrait, ZeroPoly}; use std::cmp::{min, Ordering}; -use std::ops::Neg; -pub(crate) fn pad_poly(poly: &PolyData, new_length: usize) -> Result, String> { - if new_length <= poly.coeffs.len() { - return Ok(poly.coeffs.clone()); +#[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; + +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", + )); } - let mut out = poly.coeffs.to_vec(); + poly.resize(new_length, BlstFr::zero()); - for _i in poly.coeffs.len()..new_length { - out.push(BlstFr::zero()) + Ok(poly) +} + +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", + )); } - Ok(out) + coeffs.resize(new_length, T::default()); + + Ok(coeffs) } -impl ZeroPoly for LFFTSettings { +impl LFFTSettings { fn do_zero_poly_mul_partial( &self, - indices: &[usize], + idxs: &[usize], stride: usize, - ) -> Result { - if indices.is_empty() { - return Err(String::from("idx array must be non-zero")); + ) -> Result, String> { + if idxs.is_empty() { + return Err(String::from("idx array must not be empty")); } - let blstpoly = PolyData { - coeffs: vec![BlstFr::one(); indices.len() + 1], - }; - let mut poly = blst_poly_into_pc_poly(&blstpoly.coeffs); - poly.coeffs[0] = (self.brp_roots_of_unity[indices[0] * stride]).fr.neg(); - - for (i, indice) in indices.iter().enumerate().skip(1) { - let neg_di = (self.brp_roots_of_unity[indice * stride]).fr.neg(); - - poly.coeffs[i] = neg_di + poly.coeffs[i - 1]; - - let mut j = i - 1; - while j > 0 { - let temp = poly.coeffs[j] * neg_di; - poly.coeffs[j] = temp + poly.coeffs[j - 1]; - j -= 1; + + // Makes use of long multiplication in terms of (x - w_0)(x - w_1).. + let mut coeffs = SmallVec::<[BlstFr; 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]); } - poly.coeffs[0] *= neg_di; + // Multiply x^0 member by - w_i + coeffs[0] = coeffs[0].mul(&neg_di); } - Ok(pc_poly_into_blst_poly(poly)) - } + coeffs.resize(idxs.len() + 1, BlstFr::one()); - fn reduce_partials(&self, len_out: usize, partials: &[PolyData]) -> Result { - let mut out_degree: usize = 0; - for partial in partials { - out_degree += partial.coeffs.len() - 1; - } + Ok(coeffs) + } - if out_degree + 1 > len_out { + fn reduce_partials( + &self, + domain_size: usize, + partial_coeffs: SmallVec<[SmallVec<[BlstFr; 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")); } - let mut p_partial = pad_poly(&partials[0], len_out).unwrap(); - let mut mul_eval_ps = self.fft_fr(&p_partial, false).unwrap(); + if partial_coeffs.is_empty() { + return Err(String::from("partials must not be empty")); + } - for partial in partials.iter().skip(1) { - p_partial = pad_poly(partial, len_out)?; + // 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 p_eval = self.fft_fr(&p_partial, false).unwrap(); - for j in 0..len_out { - mul_eval_ps[j].fr *= p_eval[j].fr; - } + 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<[BlstFr; DEGREE_OF_PARTIAL]> = + smallvec![BlstFr::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<[BlstFr; DEGREE_OF_PARTIAL]> = + smallvec![BlstFr::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 coeffs = self.fft_fr(&mul_eval_ps, true)?; + let mut coeffs = smallvec![BlstFr::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); - let out = PolyData { - coeffs: coeffs[..(out_degree + 1)].to_vec(), - }; + Ok(coeffs) + } +} - Ok(out) +impl ZeroPoly for LFFTSettings { + fn do_zero_poly_mul_partial(&self, idxs: &[usize], stride: usize) -> Result { + self.do_zero_poly_mul_partial(idxs, stride) + .map(|coeffs| PolyData { + coeffs: coeffs.into_vec(), + }) + } + + fn reduce_partials( + &self, + domain_size: usize, + partials: &[PolyData], + ) -> Result { + self.reduce_partials( + domain_size, + partials + .iter() + .map(|partial| SmallVec::from_slice(&partial.coeffs)) + .collect(), + ) + .map(|coeffs| PolyData { + coeffs: coeffs.into_vec(), + }) } fn zero_poly_via_multiplication( &self, - length: usize, - missing_indices: &[usize], + domain_size: usize, + missing_idxs: &[usize], ) -> Result<(Vec, PolyData), String> { let zero_eval: Vec; let mut zero_poly: PolyData; - if missing_indices.is_empty() { + if missing_idxs.is_empty() { zero_eval = Vec::new(); zero_poly = PolyData { coeffs: Vec::new() }; return Ok((zero_eval, zero_poly)); } - if missing_indices.len() >= length { + if missing_idxs.len() >= domain_size { return Err(String::from("Missing idxs greater than domain size")); - } else if length > self.max_width { + } else if domain_size > self.max_width { return Err(String::from( "Domain size greater than fft_settings.max_width", )); - } else if !length.is_power_of_two() { + } else if !domain_size.is_power_of_two() { return Err(String::from("Domain size must be a power of 2")); } - let degree_of_partial = 256; - let missing_per_partial = degree_of_partial - 1; - let domain_stride = self.max_width / length; - let mut partial_count = - (missing_per_partial + 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)?; + 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 = PolyData { + coeffs: self + .do_zero_poly_mul_partial(missing_idxs, domain_stride)? + .into_vec(), + }; } else { - let mut work = vec![BlstFr::zero(); next_pow_of_2(partial_count * degree_of_partial)]; - - let mut partial_lens = Vec::new(); - - let mut offset = 0; - let mut out_offset = 0; - let max = missing_indices.len(); - - for _i in 0..partial_count { - let end = min(offset + missing_per_partial, max); - - let mut partial = - self.do_zero_poly_mul_partial(&missing_indices[offset..end], domain_stride)?; - partial.coeffs = pad_poly(&partial, degree_of_partial)?; - work.splice( - out_offset..(out_offset + degree_of_partial), - partial.coeffs.to_vec(), + // Otherwise, construct a set of partial polynomials + // Save all constructed polynomials in a shared 'work' vector + let mut work = vec![BlstFr::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", ); - partial_lens.push(degree_of_partial); - - offset += missing_per_partial; - out_offset += degree_of_partial; - } + work[..DEGREE_OF_PARTIAL].copy_from_slice(&partial_coeffs); + }); + // Adjust last length to match its actual length partial_lens[partial_count - 1] = - 1 + missing_indices.len() - (partial_count - 1) * missing_per_partial; + 1 + missing_idxs.len() - (partial_count - 1) * missing_per_partial; - let reduction_factor = 4; + // 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 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, length); - let partials_num = min(reduction_factor, partial_count - start); - - let mut partial_vec = Vec::new(); - for j in 0..partials_num { - let k = (start + j) * partial_size; - partial_vec.push(PolyData { - coeffs: work[k..(k + partial_lens[i + j])].to_vec(), - }); + 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_poly = self.reduce_partials(reduced_len, &partial_vec)?; - partial_lens[i] = reduced_poly.coeffs.len(); - reduced_poly.coeffs = pad_poly(&reduced_poly, partial_size * partials_num)?; - work.splice( - (start * partial_size) - ..(start * partial_size + reduced_poly.coeffs.len()), - reduced_poly.coeffs, - ); + 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 = PolyData { coeffs: work }; } - match zero_poly.coeffs.len().cmp(&length) { - Ordering::Less => zero_poly.coeffs = pad_poly(&zero_poly, length)?, - Ordering::Greater => zero_poly.coeffs = zero_poly.coeffs[..length].to_vec(), + // 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)) } } From c1208a7789222403296660c64da5e5213bf990d9 Mon Sep 17 00:00:00 2001 From: Andenis Date: Wed, 6 Nov 2024 22:22:21 +0200 Subject: [PATCH 12/21] Fix fft_g1.rs problems --- arkworks3/src/fft_g1.rs | 136 ++++++------------------------------- arkworks3/src/kzg_types.rs | 2 +- 2 files changed, 22 insertions(+), 116 deletions(-) diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index 6eb0df651..d7a5f3378 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -1,20 +1,16 @@ use crate::kzg_proofs::LFFTSettings; use crate::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine}; -use kzg::cfg_into_iter; -#[cfg(feature = "parallel")] -use rayon::prelude::*; +use crate::kzg_types::ArkG1ProjAddAffine; + +use kzg::msm::msm_impls::msm; -use ark_ec::ProjectiveCurve; -use ark_ff::PrimeField; use kzg::msm::precompute::PrecomputationTable; use kzg::{Fr as KzgFr, G1Mul}; use kzg::{FFTG1, G1}; -use std::ops::MulAssign; extern crate alloc; -#[allow(unused_variables)] pub fn g1_linear_combination( out: &mut ArkG1, points: &[ArkG1], @@ -22,100 +18,12 @@ pub fn g1_linear_combination( len: usize, precomputation: Option<&PrecomputationTable>, ) { - #[cfg(feature = "sppark")] - { - use ark_bls12_381::{Fr, G1Affine}; - use ark_ec::msm::VariableBaseMSM; - use ark_ff::BigInteger256; - use kzg::{G1Mul, G1}; - - if len < 8 { - *out = ArkG1::default(); - for i in 0..len { - let tmp = points[i].mul(&scalars[i]); - out.add_or_dbl_assign(&tmp); - } - - return; - } - - let scalars = - unsafe { alloc::slice::from_raw_parts(scalars.as_ptr() as *const BigInteger256, len) }; - - let point = if let Some(precomputation) = precomputation { - rust_kzg_arkworks3_sppark::multi_scalar_mult_prepared::( - precomputation.table, - scalars, - ) - } else { - let affines = kzg::msm::msm_impls::batch_convert::(&points); - let affines = - unsafe { alloc::slice::from_raw_parts(affines.as_ptr() as *const G1Affine, len) }; - rust_kzg_arkworks3_sppark::multi_scalar_mult::(&affines[0..len], scalars) - }; - - *out = ArkG1(point); - } - - #[cfg(feature = "sppark_wlc")] - { - use ark_bls12_381::{Fr, G1Affine}; - use ark_ff::BigInteger256; - use kzg::{G1Mul, G1}; - use rust_kzg_arkworks3_sppark_wlc::MultiScalarMultContext; - - if len < 8 { - *out = ArkG1::default(); - for i in 0..len { - let tmp = points[i].mul(&scalars[i]); - out.add_or_dbl_assign(&tmp); - } - - return; - } - - let ark_scalars = cfg_into_iter!(&scalars[0..len]) - .map(|scalar| scalar.fr.into_repr()) - .collect::>(); - - let mut context = if let Some(context) = precomputation { - let table = context.table; - MultiScalarMultContext { context: table } - } else { - let affines = kzg::msm::msm_impls::batch_convert::(&points); - let affines = - unsafe { alloc::slice::from_raw_parts(affines.as_ptr() as *const G1Affine, len) }; - - rust_kzg_arkworks3_sppark_wlc::multi_scalar_mult_init(affines) - }; - - let msm_results = rust_kzg_arkworks3_sppark_wlc::multi_scalar_mult::( - &mut context, - len, - unsafe { std::mem::transmute::<&[_], &[BigInteger256]>(&ark_scalars) }, - ); - - *out = ArkG1(msm_results[0]); - - if precomputation.is_none() { - rust_kzg_arkworks3_sppark_wlc::multi_scalar_mult_free(&mut context); - } - } - - #[cfg(not(any(feature = "sppark", feature = "sppark_wlc")))] - { - use ark_ec::msm::VariableBaseMSM; - let ark_points = cfg_into_iter!(&points[0..len]) - .map(|point| point.0.into_affine()) - .collect::>(); - let ark_scalars = cfg_into_iter!(&scalars[0..len]) - .map(|scalar| scalar.fr.into_repr()) - .collect::>(); - *out = ArkG1(VariableBaseMSM::multi_scalar_mul( - ark_points.as_slice(), - ark_scalars.as_slice(), - )); - } + *out = msm::( + points, + scalars, + len, + precomputation, + ); } pub fn make_data(data: usize) -> Vec { @@ -133,29 +41,31 @@ pub fn make_data(data: usize) -> Vec { impl FFTG1 for LFFTSettings { fn fft_g1(&self, data: &[ArkG1], inverse: bool) -> Result, String> { if data.len() > self.max_width { - return Err(String::from("data length is longer than allowed max width")); - } - if !data.len().is_power_of_two() { - return Err(String::from("data length is not power of 2")); + 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: usize = self.max_width / data.len(); + let stride = self.max_width / data.len(); let mut ret = vec![ArkG1::default(); data.len()]; let roots = if inverse { &self.reverse_roots_of_unity } else { - &self.brp_roots_of_unity + &self.roots_of_unity }; - fft_g1_fast(&mut ret, data, 1, roots, stride, 1); + fft_g1_fast(&mut ret, data, 1, roots, stride); if inverse { let inv_fr_len = ArkFr::from_u64(data.len() as u64).inverse(); ret[..data.len()] .iter_mut() - .for_each(|f| f.0.mul_assign(inv_fr_len.fr)); + .for_each(|f| *f = f.mul(&inv_fr_len)); } + Ok(ret) } } @@ -166,7 +76,6 @@ pub fn fft_g1_slow( stride: usize, roots: &[ArkFr], roots_stride: usize, - _width: usize, ) { for i in 0..data.len() { ret[i] = data[0].mul(&roots[0]); @@ -185,7 +94,6 @@ pub fn fft_g1_fast( stride: usize, roots: &[ArkFr], roots_stride: usize, - _width: usize, ) { let half = ret.len() / 2; if half > 0 { @@ -193,8 +101,8 @@ pub fn fft_g1_fast( { let (lo, hi) = ret.split_at_mut(half); rayon::join( - || fft_g1_fast(hi, &data[stride..], stride * 2, roots, roots_stride * 2, 1), - || fft_g1_fast(lo, data, stride * 2, roots, roots_stride * 2, 1), + || fft_g1_fast(hi, &data[stride..], stride * 2, roots, roots_stride * 2), + || fft_g1_fast(lo, data, stride * 2, roots, roots_stride * 2), ); } @@ -206,7 +114,6 @@ pub fn fft_g1_fast( stride * 2, roots, roots_stride * 2, - 1, ); fft_g1_fast( &mut ret[half..], @@ -214,7 +121,6 @@ pub fn fft_g1_fast( stride * 2, roots, roots_stride * 2, - 1, ); } diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 2ffe25d78..73fd1f6bc 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -1031,7 +1031,7 @@ fn g1_fft(output: &mut [ArkG1], input: &[ArkG1], s: &LFFTSettings) -> Result<(), } let roots_stride = FIELD_ELEMENTS_PER_EXT_BLOB / input.len(); - fft_g1_fast(output, input, 1, &s.roots_of_unity, roots_stride, 1); + fft_g1_fast(output, input, 1, &s.roots_of_unity, roots_stride); Ok(()) } From b600a988f7514798d8997f3c79f8eb2a48913126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 7 Nov 2024 13:09:23 +0200 Subject: [PATCH 13/21] fixed kzg_types, das, poly and utils --- arkworks3/src/das.rs | 36 ++--- arkworks3/src/kzg_types.rs | 84 +++++++++-- arkworks3/src/poly.rs | 302 ++++++++++++------------------------- arkworks3/src/utils.rs | 40 ++--- 4 files changed, 203 insertions(+), 259 deletions(-) diff --git a/arkworks3/src/das.rs b/arkworks3/src/das.rs index 02425d095..717817c5d 100644 --- a/arkworks3/src/das.rs +++ b/arkworks3/src/das.rs @@ -57,31 +57,27 @@ impl LFFTSettings { } impl DAS for LFFTSettings { - fn das_fft_extension(&self, vals: &[BlstFr]) -> Result, String> { - if vals.is_empty() { - return Err(String::from("vals can not be empty")); - } - if !vals.len().is_power_of_two() { - return Err(String::from("vals lenght has to be power of 2")); - } - if vals.len() * 2 > self.max_width { + fn das_fft_extension(&self, evens: &[BlstFr]) -> 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( - "vals lenght * 2 has to equal or less than FFTSetings max width", + "Supplied list is longer than the available max width", )); } - let mut vals = vals.to_vec(); - let stride = self.max_width / (vals.len() * 2); - - self.das_fft_extension_stride(&mut vals, stride); + // 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); - let invlen = BlstFr::from_u64(vals.len() as u64); - let invlen = invlen.inverse(); - - for val in &mut vals { - val.fr *= invlen.fr - } + // TODO: explain why each odd member is multiplied by euclidean inverse of length + let mut inv_len = BlstFr::from_u64(odds.len() as u64); + inv_len = inv_len.eucl_inverse(); + let odds = odds.iter().map(|f| f.mul(&inv_len)).collect(); - Ok(vals) + Ok(odds) } } diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 73fd1f6bc..92e932af7 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -1,7 +1,7 @@ use crate::consts::SCALE2_ROOT_OF_UNITY; use crate::fft_g1::{fft_g1_fast, g1_linear_combination}; pub use crate::kzg_proofs::{expand_root_of_unity, pairings_verify, LFFTSettings, LKZGSettings}; -use crate::poly::{poly_fast_div, poly_inverse, poly_long_div, poly_mul_direct, poly_mul_fft}; +// use crate::poly::{poly_fast_div, poly_inverse, poly_long_div, poly_mul_direct, poly_mul_fft}; use crate::recover::{scale_poly, unscale_poly}; use crate::utils::{ blst_fp_into_pc_fq, blst_fr_into_pc_fr, blst_p1_into_pc_g1projective, @@ -912,42 +912,104 @@ impl Poly for PolyData { unscale_poly(self); } - fn inverse(&mut self, new_len: usize) -> Result { - poly_inverse(self, new_len) + 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 = PolyData { + coeffs: vec![ArkFr::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 = FsFFTSettings::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 = kzg::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, x: &Self) -> Result { if x.len() >= self.len() || x.len() < 128 { - poly_long_div(self, x) + self.long_div(x) } else { - poly_fast_div(self, x) + self.fast_div(x) } } fn long_div(&mut self, x: &Self) -> Result { - poly_long_div(self, x) + self.long_div(x) } fn fast_div(&mut self, x: &Self) -> Result { - poly_fast_div(self, x) + self.fast_div(x) } fn mul_direct(&mut self, x: &Self, len: usize) -> Result { - poly_mul_direct(self, x, len) + self.mul_direct(x, len) } } impl FFTSettingsPoly for LFFTSettings { fn poly_mul_fft( a: &PolyData, - x: &PolyData, + b: &PolyData, len: usize, - fs: Option<&LFFTSettings>, + _fs: Option<&LFFTSettings>, ) -> Result { - poly_mul_fft(a, x, fs, len) + b.mul_fft(a, len) } } + impl Default for LFFTSettings { fn default() -> Self { Self { diff --git a/arkworks3/src/poly.rs b/arkworks3/src/poly.rs index a85757169..d6a355987 100644 --- a/arkworks3/src/poly.rs +++ b/arkworks3/src/poly.rs @@ -1,5 +1,5 @@ use super::kzg_proofs::LFFTSettings; -use super::utils::{blst_poly_into_pc_poly, PolyData}; +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; @@ -11,241 +11,127 @@ 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 = LFFTSettings::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<&LFFTSettings>, - 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<&LFFTSettings>, - 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); - LFFTSettings::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) -} +} \ No newline at end of file diff --git a/arkworks3/src/utils.rs b/arkworks3/src/utils.rs index 2dab77124..0f6312f7d 100644 --- a/arkworks3/src/utils.rs +++ b/arkworks3/src/utils.rs @@ -66,14 +66,14 @@ pub(crate) fn fft_settings_to_rust( let roots_of_unity = unsafe { core::slice::from_raw_parts(settings.roots_of_unity, FIELD_ELEMENTS_PER_EXT_BLOB + 1) .iter() - .map(|r| ArkFr::from_blst_fr(*r)) + .map(|r| ArkFr(*r)) .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| ArkFr::from_blst_fr(*r)) + .map(|r| ArkFr(*r)) .collect::>() }; @@ -83,7 +83,7 @@ pub(crate) fn fft_settings_to_rust( FIELD_ELEMENTS_PER_EXT_BLOB + 1, ) .iter() - .map(|r| ArkFr::from_blst_fr(*r)) + .map(|r| ArkFr(*r)) .collect::>() }; @@ -110,13 +110,13 @@ pub(crate) fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result>(), g1_values_lagrange_brp: unsafe { core::slice::from_raw_parts(c_settings.g1_values_lagrange_brp, FIELD_ELEMENTS_PER_BLOB) } .iter() - .map(|r| ArkG1::from_blst_p1(*r)) + .map(|r| ArkG1(*r)) .collect::>(), g2_values_monomial: unsafe { core::slice::from_raw_parts(c_settings.g2_values_monomial, TRUSTED_SETUP_NUM_G2_POINTS) @@ -134,7 +134,7 @@ pub(crate) fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result>() }) .collect::>(), @@ -149,7 +149,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { .fs .roots_of_unity .iter() - .map(|r| r.to_blst_fr()) + .map(|r| r.0) .collect::>() .into_boxed_slice(), ) @@ -159,7 +159,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { .fs .brp_roots_of_unity .iter() - .map(|r| r.to_blst_fr()) + .map(|r| r.0) .collect::>() .into_boxed_slice(), ) @@ -169,7 +169,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { .fs .reverse_roots_of_unity .iter() - .map(|r| r.to_blst_fr()) + .map(|r| r.0) .collect::>() .into_boxed_slice(), ) @@ -178,7 +178,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { rust_settings .g1_values_monomial .iter() - .map(|r| r.to_blst_p1()) + .map(|r| r.0) .collect::>() .into_boxed_slice(), ) @@ -187,7 +187,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { rust_settings .g1_values_lagrange_brp .iter() - .map(|r| r.to_blst_p1()) + .map(|r| r.0) .collect::>() .into_boxed_slice(), ) @@ -208,7 +208,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { .map(|r| { Box::leak( r.iter() - .map(|it| it.to_blst_p1()) + .map(|it| it.0) .collect::>() .into_boxed_slice(), ) @@ -227,18 +227,18 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { pub fn pc_poly_into_blst_poly(poly: DensePoly<_Fr>) -> PolyData { let mut bls_pol: Vec = { Vec::new() }; for x in poly.coeffs { - bls_pol.push(ArkFr { fr: x }); + bls_pol.push(ArkFr::default()); } PolyData { coeffs: bls_pol } } -pub fn blst_poly_into_pc_poly(pd: &[ArkFr]) -> DensePoly<_Fr> { - let mut poly: Vec<_Fr> = vec![_Fr::default(); pd.len()]; - for i in 0..pd.len() { - poly[i] = pd[i].fr; - } - DensePoly::from_coefficients_vec(poly) -} +// pub fn blst_poly_into_pc_poly(pd: &[ArkFr]) -> DensePoly<_Fr> { +// let mut poly: Vec<_Fr> = vec![_Fr::default(); pd.len()]; +// for i in 0..pd.len() { +// poly[i] = pd[i].0.; +// } +// DensePoly::from_coefficients_vec(poly) +// } pub const fn pc_fq_into_blst_fp(fq: Fq) -> Fp { Fp { l: fq.0 .0 } From 64ae9c17765514abeee597c409adfb2334772123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 7 Nov 2024 13:46:25 +0200 Subject: [PATCH 14/21] changed setting names to add L at the start and re-added _width into fft_g1 --- arkworks3/benches/das.rs | 2 +- arkworks3/benches/eip_4844.rs | 2 +- arkworks3/benches/fft.rs | 2 +- arkworks3/benches/fk_20.rs | 2 +- arkworks3/benches/kzg.rs | 2 +- arkworks3/benches/recover.rs | 2 +- arkworks3/benches/zero_poly.rs | 2 +- arkworks3/src/fft_g1.rs | 26 +++++----- arkworks3/src/kzg_proofs.rs | 4 +- arkworks3/src/kzg_types.rs | 92 +++++++++++++++++++++------------- arkworks3/src/utils.rs | 4 +- arkworks3/tests/consts.rs | 6 +-- arkworks3/tests/das.rs | 6 +-- arkworks3/tests/eip_4844.rs | 32 ++++++------ arkworks3/tests/fft_fr.rs | 10 ++-- arkworks3/tests/fft_g1.rs | 2 +- arkworks3/tests/fk20_proofs.rs | 2 +- arkworks3/tests/kzg_proofs.rs | 2 +- arkworks3/tests/poly.rs | 2 +- arkworks3/tests/recover.rs | 2 +- arkworks3/tests/zero_poly.rs | 2 +- 21 files changed, 115 insertions(+), 91 deletions(-) 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/fk_20.rs b/arkworks3/benches/fk_20.rs index 3f9a6fa21..847c4d97e 100644 --- a/arkworks3/benches/fk_20.rs +++ b/arkworks3/benches/fk_20.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::fk20::{bench_fk_multi_da, bench_fk_single_da}; use rust_kzg_arkworks3::fk20_proofs::{KzgFK20MultiSettings, KzgFK20SingleSettings}; -use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, FFTSettings, KZGSettings}; +use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, 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/kzg.rs b/arkworks3/benches/kzg.rs index f90bc381b..717470710 100644 --- a/arkworks3/benches/kzg.rs +++ b/arkworks3/benches/kzg.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::kzg::{bench_commit_to_poly, bench_compute_proof_single}; -use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, FFTSettings, KZGSettings}; +use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, 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/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/fft_g1.rs b/arkworks3/src/fft_g1.rs index d7a5f3378..24717c61d 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -11,6 +11,7 @@ use kzg::{FFTG1, G1}; extern crate alloc; +#[allow(unused_variables)] pub fn g1_linear_combination( out: &mut ArkG1, points: &[ArkG1], @@ -57,7 +58,7 @@ impl FFTG1 for LFFTSettings { &self.roots_of_unity }; - fft_g1_fast(&mut ret, data, 1, roots, stride); + fft_g1_fast(&mut ret, data, 1, roots, stride, 1); if inverse { let inv_fr_len = ArkFr::from_u64(data.len() as u64).inverse(); @@ -76,13 +77,16 @@ pub fn fft_g1_slow( stride: usize, roots: &[ArkFr], roots_stride: usize, + _width: 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 jv = data[j * stride]; - let r = roots[((i * j) % data.len()) * roots_stride]; - let v = jv.mul(&r); + let v = data[j * stride].mul(&roots[((i * j) % data.len()) * roots_stride]); ret[i] = ret[i].add_or_dbl(&v); } } @@ -94,6 +98,7 @@ pub fn fft_g1_fast( stride: usize, roots: &[ArkFr], roots_stride: usize, + _width: usize, ) { let half = ret.len() / 2; if half > 0 { @@ -101,26 +106,21 @@ pub fn fft_g1_fast( { let (lo, hi) = ret.split_at_mut(half); rayon::join( - || fft_g1_fast(hi, &data[stride..], stride * 2, roots, roots_stride * 2), || 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 * 2, roots, roots_stride * 2, 1); fft_g1_fast( &mut ret[half..], &data[stride..], stride * 2, roots, roots_stride * 2, + 1 ); } @@ -132,4 +132,4 @@ pub fn fft_g1_fast( } else { ret[0] = data[0]; } -} +} \ No newline at end of file diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 9f89d7512..0d8eee7f9 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -4,6 +4,7 @@ extern crate alloc; use super::utils::PolyData; use crate::kzg_types::{ArkFp, ArkFr, ArkG1Affine}; use crate::kzg_types::{ArkFr as BlstFr, ArkG1, ArkG2}; +use crate::Pairing; use alloc::sync::Arc; use ark_bls12_381::Bls12_381; use ark_ec::{PairingEngine, ProjectiveCurve}; @@ -78,7 +79,6 @@ pub fn generate_trusted_setup( } pub fn pairings_verify(a1: &ArkG1, a2: &ArkG2, b1: &ArkG1, b2: &ArkG2) -> bool { - // TODO: Should look into rewriting this without blst methods. Not sure if it is possible though. let mut aa1 = blst_p1_affine::default(); let mut bb1 = blst_p1_affine::default(); @@ -97,7 +97,7 @@ pub fn pairings_verify(a1: &ArkG1, a2: &ArkG2, b1: &ArkG1, b2: &ArkG2) -> bool { blst_p2_to_affine(&mut bb2, &b2.0); let dst = [0u8; 3]; - let mut pairing_blst = blst::Pairing::new(false, &dst); + let mut pairing_blst = Pairing::new(false, &dst); pairing_blst.raw_aggregate(&aa2, &aa1); pairing_blst.raw_aggregate(&bb2, &bb1); let gt_point = pairing_blst.as_fp12().final_exp(); diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 92e932af7..6fa387a8b 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -642,22 +642,18 @@ impl PairingVerify for ArkG1 { #[repr(C)] #[derive(Debug, Default, PartialEq, Eq, Clone)] -pub struct ArkG2(pub GroupProjective); +pub struct ArkG2(pub blst_p2); impl ArkG2 { - pub fn from_blst_p2(p2: blst::blst_p2) -> Self { - Self(blst_p2_into_pc_g2projective(&p2)) - } - - pub fn to_blst_p2(&self) -> blst::blst_p2 { - pc_g2projective_into_blst_p2(self.0) + pub(crate) const fn from_xyz(x: blst_fp2, y: blst_fp2, z: blst_fp2) -> Self { + ArkG2(blst_p2 { x, y, z }) } } impl G2 for ArkG2 { fn generator() -> Self { - ArkG2::from_blst_p2(P2 { - x: blst_fp2 { + ArkG2::from_xyz( + blst_fp2 { fp: [ blst_fp { l: [ @@ -681,7 +677,7 @@ impl G2 for ArkG2 { }, ], }, - y: blst_fp2 { + blst_fp2 { fp: [ blst_fp { l: [ @@ -705,7 +701,7 @@ impl G2 for ArkG2 { }, ], }, - z: blst_fp2 { + blst_fp2 { fp: [ blst_fp { l: [ @@ -729,12 +725,12 @@ impl G2 for ArkG2 { }, ], }, - }) + ) } fn negative_generator() -> Self { - ArkG2::from_blst_p2(P2 { - x: blst_fp2 { + ArkG2::from_xyz( + blst_fp2 { fp: [ blst_fp { l: [ @@ -758,7 +754,7 @@ impl G2 for ArkG2 { }, ], }, - y: blst_fp2 { + blst_fp2 { fp: [ blst_fp { l: [ @@ -782,7 +778,7 @@ impl G2 for ArkG2 { }, ], }, - z: blst_fp2 { + blst_fp2 { fp: [ blst_fp { l: [ @@ -806,7 +802,7 @@ impl G2 for ArkG2 { }, ], }, - }) + ) } #[allow(clippy::bind_instead_of_map)] @@ -821,44 +817,72 @@ impl G2 for ArkG2 { ) }) .and_then(|bytes: &[u8; BYTES_PER_G2]| { - let mut blst_affine = blst_p2_affine::default(); - let result = unsafe { blst_p2_uncompress(&mut blst_affine, bytes.as_ptr()) }; - - if result != BLST_ERROR::BLST_SUCCESS { - return Err("Failed to deserialize G1".to_owned()); + 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_p2_uncompress(&mut tmp, bytes.as_ptr()) != BLST_ERROR::BLST_SUCCESS { + return Err("Failed to uncompress".to_string()); + } + blst_p2_from_affine(&mut g2, &tmp); } - - let mut blst_point = blst_p2::default(); - unsafe { blst_p2_from_affine(&mut blst_point, &blst_affine) }; - - Ok(ArkG2::from_blst_p2(blst_point)) + Ok(ArkG2(g2)) }) } fn to_bytes(&self) -> [u8; 96] { - <[u8; 96]>::try_from(self.0.x.c0.0.to_bytes_le()).unwrap() + let mut out = [0u8; BYTES_PER_G2]; + unsafe { + blst_p2_compress(out.as_mut_ptr(), &self.0); + } + out } fn add_or_dbl(&mut self, b: &Self) -> Self { - Self(self.0 + b.0) + let mut result = blst_p2::default(); + unsafe { + blst_p2_add_or_double(&mut result, &self.0, &b.0); + } + Self(result) } fn dbl(&self) -> Self { - Self(self.0.double()) + let mut result = blst_p2::default(); + unsafe { + blst_p2_double(&mut result, &self.0); + } + Self(result) } fn sub(&self, b: &Self) -> Self { - Self(self.0 - b.0) + let mut bneg: blst_p2 = b.0; + let mut result = blst_p2::default(); + unsafe { + blst_p2_cneg(&mut bneg, true); + blst_p2_add_or_double(&mut result, &self.0, &bneg); + } + Self(result) } fn equals(&self, b: &Self) -> bool { - self.0.eq(&b.0) + unsafe { blst_p2_is_equal(&self.0, &b.0) } } } impl G2Mul for ArkG2 { fn mul(&self, b: &ArkFr) -> Self { - Self(self.0.mul(b.to_u64_arr())) + let mut result = blst_p2::default(); + let mut scalar = blst_scalar::default(); + unsafe { + blst_scalar_from_fr(&mut scalar, &b.0); + blst_p2_mult( + &mut result, + &self.0, + scalar.b.as_ptr(), + 8 * core::mem::size_of::(), + ); + } + Self(result) } } @@ -1093,7 +1117,7 @@ fn g1_fft(output: &mut [ArkG1], input: &[ArkG1], s: &LFFTSettings) -> Result<(), } let roots_stride = FIELD_ELEMENTS_PER_EXT_BLOB / input.len(); - fft_g1_fast(output, input, 1, &s.roots_of_unity, roots_stride); + fft_g1_fast(output, input, 1, &s.roots_of_unity, roots_stride, 1); Ok(()) } diff --git a/arkworks3/src/utils.rs b/arkworks3/src/utils.rs index 0f6312f7d..bfa7a3ccf 100644 --- a/arkworks3/src/utils.rs +++ b/arkworks3/src/utils.rs @@ -122,7 +122,7 @@ pub(crate) fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result>(), x_ext_fft_columns: unsafe { core::slice::from_raw_parts( @@ -196,7 +196,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { rust_settings .g2_values_monomial .iter() - .map(|r| r.to_blst_p2()) + .map(|r| r.0) .collect::>() .into_boxed_slice(), ) 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..d0aaf9022 100644 --- a/arkworks3/tests/eip_4844.rs +++ b/arkworks3/tests/eip_4844.rs @@ -22,7 +22,7 @@ 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 +43,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -60,7 +60,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -79,7 +79,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -101,7 +101,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -123,7 +123,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -145,7 +145,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -165,7 +165,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -185,7 +185,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -205,7 +205,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -225,7 +225,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -243,7 +243,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -261,7 +261,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -279,7 +279,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -293,7 +293,7 @@ mod tests { ArkG1, ArkG2, PolyData, - FFTSettings, + LFFTSettings, KZGSettings, ArkFp, ArkG1Affine, @@ -311,7 +311,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/fk20_proofs.rs b/arkworks3/tests/fk20_proofs.rs index 82666d626..36bdc9686 100644 --- a/arkworks3/tests/fk20_proofs.rs +++ b/arkworks3/tests/fk20_proofs.rs @@ -3,7 +3,7 @@ mod tests { use kzg_bench::tests::fk20_proofs::*; use rust_kzg_arkworks3::fk20_proofs::{KzgFK20MultiSettings, KzgFK20SingleSettings}; - use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, FFTSettings, KZGSettings}; + use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, LFFTSettings as FFTSettings, LKZGSettings as KZGSettings}; use rust_kzg_arkworks3::kzg_types::{ArkFp, ArkFr as BlstFr, ArkG1Affine}; use rust_kzg_arkworks3::kzg_types::{ArkG1, ArkG2}; use rust_kzg_arkworks3::utils::PolyData; diff --git a/arkworks3/tests/kzg_proofs.rs b/arkworks3/tests/kzg_proofs.rs index 94686a1bf..73c19422e 100644 --- a/arkworks3/tests/kzg_proofs.rs +++ b/arkworks3/tests/kzg_proofs.rs @@ -3,7 +3,7 @@ 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_arkworks3::kzg_proofs::{generate_trusted_setup, FFTSettings, KZGSettings}; + use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, 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/tests/poly.rs b/arkworks3/tests/poly.rs index 4460ffdf1..19c60a3cb 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; 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; From d019af0925fa238034f6222753b0b20826878942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 7 Nov 2024 16:03:07 +0200 Subject: [PATCH 15/21] fixed das and div by zero tests --- arkworks3/src/das.rs | 94 ++++++++++++++------------- arkworks3/src/fft_g1.rs | 1 - arkworks3/src/kzg_types.rs | 119 +++++++++++++++++++++++++++++++++-- arkworks3/tests/bls12_381.rs | 1 - arkworks3/tests/poly.rs | 1 - 5 files changed, 164 insertions(+), 52 deletions(-) diff --git a/arkworks3/src/das.rs b/arkworks3/src/das.rs index 717817c5d..61bfbe0f4 100644 --- a/arkworks3/src/das.rs +++ b/arkworks3/src/das.rs @@ -4,55 +4,63 @@ use kzg::{Fr, DAS}; use std::cmp::Ordering; impl LFFTSettings { - fn das_fft_extension_stride(&self, ab: &mut [BlstFr], stride: usize) { - match ab.len().cmp(&2_usize) { - Ordering::Less => {} - Ordering::Greater => { - let half = ab.len(); - let halfhalf = half / 2; + pub fn das_fft_extension_stride(&self, evens: &mut [BlstFr], 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]); - for i in 0..halfhalf { - let tmp1 = ab[i].add(&ab[halfhalf + i]); - let tmp2 = ab[i].sub(&ab[halfhalf + i]); - ab[halfhalf + i] = tmp2.mul(&self.reverse_roots_of_unity[i * 2 * stride]); - ab[i] = tmp1; - } + evens[0] = x.add(&y_times_root); + evens[1] = x.sub(&y_times_root); - #[cfg(feature = "parallel")] - { - if ab.len() > 32 { - let (lo, hi) = ab.split_at_mut(halfhalf); - rayon::join( - || self.das_fft_extension_stride(hi, stride * 2), - || self.das_fft_extension_stride(lo, stride * 2), - ); - } else { - self.das_fft_extension_stride(&mut ab[..halfhalf], stride * 2); - self.das_fft_extension_stride(&mut ab[halfhalf..], stride * 2); - } - } - #[cfg(not(feature = "parallel"))] - { - self.das_fft_extension_stride(&mut ab[..halfhalf], stride * 2); - self.das_fft_extension_stride(&mut ab[halfhalf..], stride * 2); - } - for i in 0..halfhalf { - let x = ab[i]; - let y = ab[halfhalf + i]; - let y_times_root = y.mul(&self.brp_roots_of_unity[(1 + 2 * i) * stride]); - ab[i] = x.add(&y_times_root); - ab[halfhalf + i] = x.sub(&y_times_root); - } + return; } - Ordering::Equal => { - let x = ab[0].add(&ab[1]); - let y = ab[0].sub(&ab[1]); - let tmp = y.mul(&self.brp_roots_of_unity[stride]); + 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; + } - ab[0] = x.add(&tmp); - ab[1] = x.sub(&tmp); + #[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: BlstFr = 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); + } } } diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index 24717c61d..2051f7437 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -11,7 +11,6 @@ use kzg::{FFTG1, G1}; extern crate alloc; -#[allow(unused_variables)] pub fn g1_linear_combination( out: &mut ArkG1, points: &[ArkG1], diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 6fa387a8b..c2d129bf8 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -1009,16 +1009,123 @@ impl Poly for PolyData { } } - fn long_div(&mut self, x: &Self) -> Result { - self.long_div(x) + 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(PolyData { 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(PolyData { coeffs: out_coeffs }) + } else { + let mut out: PolyData = PolyData { + coeffs: vec![ArkFr::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, x: &Self) -> Result { - self.fast_div(x) + 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(PolyData { coeffs: Vec::new() }); + } + + // Special case for divisor.length == 1 (it's a constant) + if divisor.len() == 1 { + let mut out = PolyData { + coeffs: vec![ArkFr::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, x: &Self, len: usize) -> Result { - self.mul_direct(x, len) + fn mul_direct(&mut self, multiplier: &Self, output_len: usize) -> Result { + if self.len() == 0 || multiplier.len() == 0 { + return Ok(PolyData::new(0)); + } + + let a_degree = self.len() - 1; + let b_degree = multiplier.len() - 1; + + let mut ret = PolyData { + coeffs: vec![kzg::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) } } 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/poly.rs b/arkworks3/tests/poly.rs index 19c60a3cb..5c796f1a6 100644 --- a/arkworks3/tests/poly.rs +++ b/arkworks3/tests/poly.rs @@ -46,7 +46,6 @@ mod tests { } #[test] - #[should_panic] fn poly_div_by_zero_() { poly_div_by_zero::(); } From 5b4493388a68a1767c9e70d6b81144de5530b7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 7 Nov 2024 16:19:05 +0200 Subject: [PATCH 16/21] removed unused imports --- arkworks3/src/fft_g1.rs | 46 +++++++++++++++++++++++++++++----- arkworks3/src/kzg_proofs.rs | 6 ----- arkworks3/src/kzg_types.rs | 49 +++++++++++++++---------------------- arkworks3/src/poly.rs | 9 +------ arkworks3/src/utils.rs | 3 +-- 5 files changed, 62 insertions(+), 51 deletions(-) diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index 2051f7437..6b918eb7e 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -18,12 +18,46 @@ pub fn g1_linear_combination( len: usize, precomputation: Option<&PrecomputationTable>, ) { - *out = msm::( - points, - scalars, - len, - precomputation, - ); + #[cfg(feature = "sppark")] + { + use blst::{blst_fr, blst_scalar, blst_scalar_from_fr}; + use kzg::{G1Mul, G1}; + + if len < 8 { + *out = FsG1::default(); + for i in 0..len { + let tmp = points[i].mul(&scalars[i]); + out.add_or_dbl_assign(&tmp); + } + + return; + } + + let scalars = + unsafe { alloc::slice::from_raw_parts(scalars.as_ptr() as *const blst_fr, len) }; + + let point = if let Some(precomputation) = precomputation { + rust_kzg_blst_sppark::multi_scalar_mult_prepared(precomputation.table, scalars) + } else { + let affines = kzg::msm::msm_impls::batch_convert::(&points); + let affines = unsafe { + alloc::slice::from_raw_parts(affines.as_ptr() as *const blst_p1_affine, len) + }; + rust_kzg_blst_sppark::multi_scalar_mult(&affines[0..len], &scalars) + }; + + *out = FsG1(point); + } + + #[cfg(not(feature = "sppark"))] + { + *out = msm::( + points, + scalars, + len, + precomputation, + ); + } } pub fn make_data(data: usize) -> Vec { diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 0d8eee7f9..b7ec5d160 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -1,15 +1,10 @@ #![allow(non_camel_case_types)] extern crate alloc; -use super::utils::PolyData; use crate::kzg_types::{ArkFp, ArkFr, ArkG1Affine}; use crate::kzg_types::{ArkFr as BlstFr, ArkG1, ArkG2}; use crate::Pairing; use alloc::sync::Arc; -use ark_bls12_381::Bls12_381; -use ark_ec::{PairingEngine, ProjectiveCurve}; -use ark_poly::Polynomial; -use ark_std::{vec, One}; use blst::{ blst_fp12_is_one, blst_p1_affine, blst_p1_cneg, blst_p1_to_affine, blst_p2_affine, blst_p2_to_affine, @@ -17,7 +12,6 @@ use blst::{ use kzg::eip_4844::hash_to_bls_field; use kzg::msm::precompute::PrecomputationTable; use kzg::{Fr, G1Mul, G2Mul, G1, G2}; -use std::ops::Neg; #[derive(Debug, Clone)] pub struct LFFTSettings { diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index c2d129bf8..e79a38e3b 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -4,22 +4,14 @@ pub use crate::kzg_proofs::{expand_root_of_unity, pairings_verify, LFFTSettings, // use crate::poly::{poly_fast_div, poly_inverse, poly_long_div, poly_mul_direct, poly_mul_fft}; use crate::recover::{scale_poly, unscale_poly}; use crate::utils::{ - blst_fp_into_pc_fq, blst_fr_into_pc_fr, blst_p1_into_pc_g1projective, - blst_p2_into_pc_g2projective, pc_fr_into_blst_fr, pc_g1projective_into_blst_p1, - pc_g2projective_into_blst_p2, PolyData, + blst_fp_into_pc_fq, PolyData, }; -use crate::P2; -use ark_bls12_381::{g1, g2, Fr, G1Affine}; +use ark_bls12_381::g1; use ark_ec::ModelParameters; -use ark_ec::{models::short_weierstrass_jacobian::GroupProjective, AffineCurve, ProjectiveCurve}; -use ark_ff::PrimeField; -use ark_ff::{biginteger::BigInteger256, BigInteger, Field}; +use ark_ec::{models::short_weierstrass_jacobian::GroupProjective, ProjectiveCurve}; +use ark_ff::Field; use ark_std::{One, Zero}; -#[cfg(feature = "rand")] -use ark_std::UniformRand; - -use blst::p1_affines; use blst::{ blst_bendian_from_scalar, blst_fp, blst_fp2, blst_fr, blst_fr_add, blst_fr_cneg, blst_fr_eucl_inverse, blst_fr_from_scalar, blst_fr_from_uint64, blst_fr_inverse, blst_fr_mul, @@ -41,21 +33,20 @@ use kzg::{ FFTFr, FFTSettings, FFTSettingsPoly, Fr as KzgFr, G1Affine as G1AffineTrait, G1Fp, G1GetFp, G1LinComb, G1Mul, G1ProjAddAffine, G2Mul, KZGSettings, PairingVerify, Poly, Scalar256, G1, G2, }; -use std::ops::{AddAssign, Neg, Sub}; extern crate alloc; use alloc::sync::Arc; -fn bytes_be_to_uint64(inp: &[u8]) -> u64 { - u64::from_be_bytes(inp.try_into().expect("Input wasn't 8 elements...")) -} +// fn bytes_be_to_uint64(inp: &[u8]) -> u64 { +// u64::from_be_bytes(inp.try_into().expect("Input wasn't 8 elements...")) +// } -const BLS12_381_MOD_256: [u64; 4] = [ - 0xffffffff00000001, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48, -]; +// const BLS12_381_MOD_256: [u64; 4] = [ +// 0xffffffff00000001, +// 0x53bda402fffe5bfe, +// 0x3339d80809a1d805, +// 0x73eda753299d7d48, +// ]; #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] pub struct ArkFr(pub blst_fr); @@ -63,13 +54,13 @@ pub struct ArkFr(pub blst_fr); // impl Fr for ArkFr { -fn bigint_check_mod_256(a: &[u64; 4]) -> bool { - let (_, overflow) = a[0].overflowing_sub(BLS12_381_MOD_256[0]); - let (_, overflow) = a[1].overflowing_sub(BLS12_381_MOD_256[1] + overflow as u64); - let (_, overflow) = a[2].overflowing_sub(BLS12_381_MOD_256[2] + overflow as u64); - let (_, overflow) = a[3].overflowing_sub(BLS12_381_MOD_256[3] + overflow as u64); - overflow -} +// fn bigint_check_mod_256(a: &[u64; 4]) -> bool { +// let (_, overflow) = a[0].overflowing_sub(BLS12_381_MOD_256[0]); +// let (_, overflow) = a[1].overflowing_sub(BLS12_381_MOD_256[1] + overflow as u64); +// let (_, overflow) = a[2].overflowing_sub(BLS12_381_MOD_256[2] + overflow as u64); +// let (_, overflow) = a[3].overflowing_sub(BLS12_381_MOD_256[3] + overflow as u64); +// overflow +// } impl KzgFr for ArkFr { fn null() -> Self { diff --git a/arkworks3/src/poly.rs b/arkworks3/src/poly.rs index d6a355987..f177c4543 100644 --- a/arkworks3/src/poly.rs +++ b/arkworks3/src/poly.rs @@ -1,15 +1,8 @@ use super::kzg_proofs::LFFTSettings; -use super::utils::{PolyData}; +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_flip(input: &PolyData) -> Result { let mut output = PolyData::new(0); diff --git a/arkworks3/src/utils.rs b/arkworks3/src/utils.rs index bfa7a3ccf..3aff5fd7e 100644 --- a/arkworks3/src/utils.rs +++ b/arkworks3/src/utils.rs @@ -19,7 +19,6 @@ use ark_bls12_381::{g1, g2, Fq, Fq2, Fr as _Fr}; use ark_ec::models::short_weierstrass_jacobian::GroupProjective; use ark_ff::{BigInteger256, BigInteger384, Fp2}; use ark_poly::univariate::DensePolynomial as DensePoly; -use ark_poly::UVPolynomial; use blst::{blst_fp, blst_fp2, blst_fr, blst_p1, blst_p2}; #[derive(Debug, PartialEq, Eq)] @@ -226,7 +225,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { pub fn pc_poly_into_blst_poly(poly: DensePoly<_Fr>) -> PolyData { let mut bls_pol: Vec = { Vec::new() }; - for x in poly.coeffs { + for _x in poly.coeffs { bls_pol.push(ArkFr::default()); } PolyData { coeffs: bls_pol } From 6294a9e2df792e4edb417009548269ccf783e4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 7 Nov 2024 19:37:13 +0200 Subject: [PATCH 17/21] fn g1_linear_combination works on a shallow implementation and should be fixed to use msm, but now tests pass --- arkworks3/src/fft_g1.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index 6b918eb7e..61bcd9991 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -51,12 +51,13 @@ pub fn g1_linear_combination( #[cfg(not(feature = "sppark"))] { - *out = msm::( - points, - scalars, - len, - precomputation, - ); + *out = ArkG1::default(); + for i in 0..len { + let tmp = points[i].mul(&scalars[i]); + out.add_or_dbl_assign(&tmp); + } + + return; } } From 49f83acce6649abe5825b37fb1330f754e8a69c6 Mon Sep 17 00:00:00 2001 From: Andenis Date: Mon, 18 Nov 2024 17:21:11 +0200 Subject: [PATCH 18/21] Fix potential problem in fft_g1.rs --- arkworks3/src/fft_g1.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index 61bcd9991..a06e7904d 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -140,8 +140,8 @@ pub fn fft_g1_fast( { 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), + || fft_g1_fast(lo, data, stride * 2, roots, roots_stride * 2, 1), + || fft_g1_fast(hi, &data[stride..], stride * 2, roots, roots_stride * 2, 1), ); } From ed3577742841a6a6f46ad285e33fb9d7706a9b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 21 Nov 2024 18:39:55 +0200 Subject: [PATCH 19/21] reverted some ArkFp and ArkG1/ArkG2 changes and re-added msm to the g1_linear_combination function --- arkworks3/src/fft_g1.rs | 17 +- arkworks3/src/kzg_proofs.rs | 43 ++--- arkworks3/src/kzg_types.rs | 339 ++++++++++++------------------------ arkworks3/src/utils.rs | 16 +- 4 files changed, 146 insertions(+), 269 deletions(-) diff --git a/arkworks3/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index a06e7904d..ee8f76e26 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -1,6 +1,6 @@ use crate::kzg_proofs::LFFTSettings; -use crate::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine}; - +use crate::kzg_types::{ArkFr, ArkG1}; +use crate::kzg_types::{ArkFp, ArkG1Affine}; use crate::kzg_types::ArkG1ProjAddAffine; use kzg::msm::msm_impls::msm; @@ -51,13 +51,12 @@ pub fn g1_linear_combination( #[cfg(not(feature = "sppark"))] { - *out = ArkG1::default(); - for i in 0..len { - let tmp = points[i].mul(&scalars[i]); - out.add_or_dbl_assign(&tmp); - } - - return; + *out = msm::( + points, + scalars, + len, + precomputation + ); } } diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index b7ec5d160..c1ffc9f73 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -3,15 +3,19 @@ extern crate alloc; use crate::kzg_types::{ArkFp, ArkFr, ArkG1Affine}; use crate::kzg_types::{ArkFr as BlstFr, ArkG1, ArkG2}; -use crate::Pairing; +use ark_bls12_381::Bls12_381; +use ark_ec::PairingEngine; use alloc::sync::Arc; +use ark_ec::ProjectiveCurve; use blst::{ blst_fp12_is_one, blst_p1_affine, blst_p1_cneg, blst_p1_to_affine, blst_p2_affine, blst_p2_to_affine, }; +use ark_std::One; use kzg::eip_4844::hash_to_bls_field; use kzg::msm::precompute::PrecomputationTable; use kzg::{Fr, G1Mul, G2Mul, G1, G2}; +use std::ops::Neg; #[derive(Debug, Clone)] pub struct LFFTSettings { @@ -73,29 +77,14 @@ pub fn generate_trusted_setup( } pub fn pairings_verify(a1: &ArkG1, a2: &ArkG2, b1: &ArkG1, b2: &ArkG2) -> bool { - let mut aa1 = blst_p1_affine::default(); - let mut bb1 = blst_p1_affine::default(); - - let mut aa2 = blst_p2_affine::default(); - let mut bb2 = blst_p2_affine::default(); - - // As an optimisation, we want to invert one of the pairings, - // so we negate one of the points. - let mut a1neg: ArkG1 = *a1; - unsafe { - blst_p1_cneg(&mut a1neg.0, true); - blst_p1_to_affine(&mut aa1, &a1neg.0); - - blst_p1_to_affine(&mut bb1, &b1.0); - blst_p2_to_affine(&mut aa2, &a2.0); - blst_p2_to_affine(&mut bb2, &b2.0); - - let dst = [0u8; 3]; - let mut pairing_blst = Pairing::new(false, &dst); - pairing_blst.raw_aggregate(&aa2, &aa1); - pairing_blst.raw_aggregate(&bb2, &bb1); - let gt_point = pairing_blst.as_fp12().final_exp(); - - blst_fp12_is_one(>_point) - } -} + let ark_a1_neg = a1.0.neg().into_affine(); + let ark_b1 = b1.0.into_affine(); + let ark_a2 = a2.0.into_affine(); + let ark_b2 = b2.0.into_affine(); + + Bls12_381::product_of_pairings(&[ + (ark_a1_neg.into(), ark_a2.into()), + (ark_b1.into(), ark_b2.into()), + ]) + .is_one() +} \ No newline at end of file diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index e79a38e3b..71baee0bd 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -4,14 +4,15 @@ pub use crate::kzg_proofs::{expand_root_of_unity, pairings_verify, LFFTSettings, // use crate::poly::{poly_fast_div, poly_inverse, poly_long_div, poly_mul_direct, poly_mul_fft}; use crate::recover::{scale_poly, unscale_poly}; use crate::utils::{ - blst_fp_into_pc_fq, PolyData, + blst_fp_into_pc_fq, blst_p1_into_pc_g1projective, blst_p2_into_pc_g2projective, pc_g1projective_into_blst_p1, pc_g2projective_into_blst_p2, PolyData }; -use ark_bls12_381::g1; -use ark_ec::ModelParameters; +use crate::P2; +use ark_bls12_381::{g1, g2, G1Affine}; +use ark_ec::{AffineCurve, ModelParameters}; use ark_ec::{models::short_weierstrass_jacobian::GroupProjective, ProjectiveCurve}; -use ark_ff::Field; +use ark_ff::{BigInteger, Field}; use ark_std::{One, Zero}; - +use std::ops::{AddAssign, Neg, Sub}; use blst::{ blst_bendian_from_scalar, blst_fp, blst_fp2, blst_fr, blst_fr_add, blst_fr_cneg, blst_fr_eucl_inverse, blst_fr_from_scalar, blst_fr_from_uint64, blst_fr_inverse, blst_fr_mul, @@ -310,32 +311,43 @@ impl KzgFr for ArkFr { #[repr(C)] #[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] -pub struct ArkG1(pub blst_p1); +pub struct ArkG1(pub GroupProjective); impl ArkG1 { - pub(crate) const fn from_xyz(x: blst_fp, y: blst_fp, z: blst_fp) -> Self { - ArkG1(blst_p1 { x, y, z }) + pub fn from_blst_p1(p1: blst_p1) -> Self { + Self(blst_p1_into_pc_g1projective(&p1)) + } + + pub fn to_blst_p1(&self) -> blst_p1 { + pc_g1projective_into_blst_p1(self.0) } } -// impl From for ArkG1 { -// fn from(p1: blst_p1) -> Self { -// Self(blst_p1_into_pc_g1projective(&p1)) -// } -// } +impl From for ArkG1 { + fn from(p1: blst_p1) -> Self { + Self(blst_p1_into_pc_g1projective(&p1)) + } +} impl G1 for ArkG1 { fn identity() -> Self { - ArkG1::from_xyz( - blst_fp { l: [0; 6] }, - blst_fp { l: [0; 6] }, - blst_fp { l: [0; 6] }, - ) + ArkG1::from_blst_p1(blst_p1 { + x: blst_fp { + l: [0, 0, 0, 0, 0, 0], + }, + y: blst_fp { + l: [0, 0, 0, 0, 0, 0], + }, + z: blst_fp { + l: [0, 0, 0, 0, 0, 0], + }, + }) } + fn generator() -> Self { - ArkG1::from_xyz( - blst_fp { + ArkG1::from_blst_p1(blst_p1 { + x: blst_fp { l: [ 0x5cb38790fd530c16, 0x7817fc679976fff5, @@ -345,7 +357,7 @@ impl G1 for ArkG1 { 0x120177419e0bfb75, ], }, - blst_fp { + y: blst_fp { l: [ 0xbaac93d50ce72271, 0x8c22631a7918fd8e, @@ -355,7 +367,7 @@ impl G1 for ArkG1 { 0x0bbc3efc5008a26a, ], }, - blst_fp { + z: blst_fp { l: [ 0x760900000002fffd, 0xebf4000bc40c0002, @@ -365,12 +377,13 @@ impl G1 for ArkG1 { 0x15f65ec3fa80e493, ], }, - ) + }) } + fn negative_generator() -> Self { - ArkG1::from_xyz( - blst_fp { + ArkG1::from_blst_p1(blst_p1 { + x: blst_fp { l: [ 0x5cb38790fd530c16, 0x7817fc679976fff5, @@ -380,7 +393,7 @@ impl G1 for ArkG1 { 0x120177419e0bfb75, ], }, - blst_fp { + y: blst_fp { l: [ 0xff526c2af318883a, 0x92899ce4383b0270, @@ -390,7 +403,7 @@ impl G1 for ArkG1 { 0x0e44d2ede9774430, ], }, - blst_fp { + z: blst_fp { l: [ 0x760900000002fffd, 0xebf4000bc40c0002, @@ -400,46 +413,18 @@ impl G1 for ArkG1 { 0x15f65ec3fa80e493, ], }, - ) + }) } #[cfg(feature = "rand")] fn rand() -> Self { - let result = ArkG1::from_xyz( - blst_fp { - l: [ - 0x5cb38790fd530c16, - 0x7817fc679976fff5, - 0x154f95c7143ba1c1, - 0xf0ae6acdf3d0e747, - 0xedce6ecc21dbf440, - 0x120177419e0bfb75, - ], - }, - blst_fp { - l: [ - 0xbaac93d50ce72271, - 0x8c22631a7918fd8e, - 0xdd595f13570725ce, - 0x51ac582950405194, - 0x0e1c8c3fad0059c0, - 0x0bbc3efc5008a26a, - ], - }, - blst_fp { - l: [ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, - ], - }, - ); - result.mul(&kzg::Fr::rand()) + use ark_ff::UniformRand; + + let mut rng = rand::thread_rng(); + Self(GroupProjective::rand(&mut rng)) } + #[allow(clippy::bind_instead_of_map)] fn from_bytes(bytes: &[u8]) -> Result { bytes @@ -462,7 +447,7 @@ impl G1 for ArkG1 { let mut blst_point = blst_p1::default(); unsafe { blst_p1_from_affine(&mut blst_point, &blst_affine) }; - Ok(ArkG1(blst_point)) + Ok(ArkG1::from_blst_p1(blst_point)) }) } @@ -474,63 +459,43 @@ impl G1 for ArkG1 { fn to_bytes(&self) -> [u8; 48] { let mut out = [0u8; BYTES_PER_G1]; unsafe { - blst_p1_compress(out.as_mut_ptr(), &self.0); + blst_p1_compress(out.as_mut_ptr(), &self.to_blst_p1()); } out } fn add_or_dbl(&self, b: &Self) -> Self { - let mut ret = Self::default(); - unsafe { - blst_p1_add_or_double(&mut ret.0, &self.0, &b.0); - } - ret + Self(self.0 + b.0) } fn is_inf(&self) -> bool { - unsafe { blst_p1_is_inf(&self.0) } + let temp = &self.0; + temp.z.is_zero() } fn is_valid(&self) -> bool { - unsafe { - // The point must be on the right subgroup - blst_p1_in_g1(&self.0) - } + unsafe { blst_p1_in_g1(&self.to_blst_p1()) } } fn dbl(&self) -> Self { - let mut result = blst_p1::default(); - unsafe { - blst_p1_double(&mut result, &self.0); - } - Self(result) + Self(self.0.double()) } fn add(&self, b: &Self) -> Self { - let mut ret = Self::default(); - unsafe { - blst_p1_add(&mut ret.0, &self.0, &b.0); - } - ret + Self(self.0 + b.0) } fn sub(&self, b: &Self) -> Self { - let mut b_negative: ArkG1 = *b; - let mut ret = Self::default(); - unsafe { - blst_p1_cneg(&mut b_negative.0, true); - blst_p1_add_or_double(&mut ret.0, &self.0, &b_negative.0); - ret - } + Self(self.0.sub(&b.0)) } fn equals(&self, b: &Self) -> bool { - unsafe { blst_p1_is_equal(&self.0, &b.0) } + self.0.eq(&b.0) } fn zero() -> Self { - ArkG1::from_xyz( - blst_fp { + ArkG1::from_blst_p1(blst_p1 { + x: blst_fp { l: [ 8505329371266088957, 17002214543764226050, @@ -540,7 +505,7 @@ impl G1 for ArkG1 { 1582556514881692819, ], }, - blst_fp { + y: blst_fp { l: [ 8505329371266088957, 17002214543764226050, @@ -550,65 +515,28 @@ impl G1 for ArkG1 { 1582556514881692819, ], }, - blst_fp { + z: blst_fp { l: [0, 0, 0, 0, 0, 0], }, - ) + }) } fn add_or_dbl_assign(&mut self, b: &Self) { - unsafe { - blst::blst_p1_add_or_double(&mut self.0, &self.0, &b.0); - } + self.0 += b.0; } fn add_assign(&mut self, b: &Self) { - unsafe { - blst::blst_p1_add(&mut self.0, &self.0, &b.0); - } + self.0.add_assign(b.0); } fn dbl_assign(&mut self) { - unsafe { - blst::blst_p1_double(&mut self.0, &self.0); - } + self.0.double_in_place(); } } impl G1Mul for ArkG1 { fn mul(&self, b: &ArkFr) -> Self { - let mut scalar: blst_scalar = blst_scalar::default(); - unsafe { - blst_scalar_from_fr(&mut scalar, &b.0); - } - - // Count the number of bytes to be multiplied. - let mut i = scalar.b.len(); - while i != 0 && scalar.b[i - 1] == 0 { - i -= 1; - } - - let mut result = Self::default(); - if i == 0 { - return ArkG1::from_xyz( - blst_fp { l: [0; 6] }, - blst_fp { l: [0; 6] }, - blst_fp { l: [0; 6] }, - ); - } else if i == 1 && scalar.b[0] == 1 { - return *self; - } else { - // Count the number of bits to be multiplied. - unsafe { - blst_p1_mult( - &mut result.0, - &self.0, - &(scalar.b[0]), - 8 * i - 7 + log_2_byte(scalar.b[i - 1]), - ); - } - } - result + Self(self.0.mul(b.to_u64_arr())) } } @@ -632,19 +560,22 @@ impl PairingVerify for ArkG1 { } #[repr(C)] -#[derive(Debug, Default, PartialEq, Eq, Clone)] -pub struct ArkG2(pub blst_p2); +#[derive(Debug, Default, PartialEq, Eq, Clone)]pub struct ArkG2(pub GroupProjective); impl ArkG2 { - pub(crate) const fn from_xyz(x: blst_fp2, y: blst_fp2, z: blst_fp2) -> Self { - ArkG2(blst_p2 { x, y, z }) + pub fn from_blst_p2(p2: blst::blst_p2) -> Self { + Self(blst_p2_into_pc_g2projective(&p2)) + } + + pub fn to_blst_p2(&self) -> blst::blst_p2 { + pc_g2projective_into_blst_p2(self.0) } } impl G2 for ArkG2 { fn generator() -> Self { - ArkG2::from_xyz( - blst_fp2 { + ArkG2::from_blst_p2(P2 { + x: blst_fp2 { fp: [ blst_fp { l: [ @@ -668,7 +599,7 @@ impl G2 for ArkG2 { }, ], }, - blst_fp2 { + y: blst_fp2 { fp: [ blst_fp { l: [ @@ -692,7 +623,7 @@ impl G2 for ArkG2 { }, ], }, - blst_fp2 { + z: blst_fp2 { fp: [ blst_fp { l: [ @@ -716,12 +647,12 @@ impl G2 for ArkG2 { }, ], }, - ) + }) } fn negative_generator() -> Self { - ArkG2::from_xyz( - blst_fp2 { + ArkG2::from_blst_p2(P2 { + x: blst_fp2 { fp: [ blst_fp { l: [ @@ -745,7 +676,7 @@ impl G2 for ArkG2 { }, ], }, - blst_fp2 { + y: blst_fp2 { fp: [ blst_fp { l: [ @@ -769,7 +700,7 @@ impl G2 for ArkG2 { }, ], }, - blst_fp2 { + z: blst_fp2 { fp: [ blst_fp { l: [ @@ -793,9 +724,10 @@ impl G2 for ArkG2 { }, ], }, - ) + }) } + #[allow(clippy::bind_instead_of_map)] fn from_bytes(bytes: &[u8]) -> Result { bytes @@ -817,63 +749,35 @@ impl G2 for ArkG2 { } blst_p2_from_affine(&mut g2, &tmp); } - Ok(ArkG2(g2)) + Ok(ArkG2::from_blst_p2(g2)) }) } fn to_bytes(&self) -> [u8; 96] { - let mut out = [0u8; BYTES_PER_G2]; - unsafe { - blst_p2_compress(out.as_mut_ptr(), &self.0); - } - out + <[u8; 96]>::try_from(self.0.x.c0.0.to_bytes_le()).unwrap() } + fn add_or_dbl(&mut self, b: &Self) -> Self { - let mut result = blst_p2::default(); - unsafe { - blst_p2_add_or_double(&mut result, &self.0, &b.0); - } - Self(result) + Self(self.0 + b.0) } fn dbl(&self) -> Self { - let mut result = blst_p2::default(); - unsafe { - blst_p2_double(&mut result, &self.0); - } - Self(result) + Self(self.0.double()) } fn sub(&self, b: &Self) -> Self { - let mut bneg: blst_p2 = b.0; - let mut result = blst_p2::default(); - unsafe { - blst_p2_cneg(&mut bneg, true); - blst_p2_add_or_double(&mut result, &self.0, &bneg); - } - Self(result) + Self(self.0 - b.0) } fn equals(&self, b: &Self) -> bool { - unsafe { blst_p2_is_equal(&self.0, &b.0) } + self.0.eq(&b.0) } } impl G2Mul for ArkG2 { fn mul(&self, b: &ArkFr) -> Self { - let mut result = blst_p2::default(); - let mut scalar = blst_scalar::default(); - unsafe { - blst_scalar_from_fr(&mut scalar, &b.0); - blst_p2_mult( - &mut result, - &self.0, - scalar.b.as_ptr(), - 8 * core::mem::size_of::(), - ); - } - Self(result) + Self(self.0.mul(b.to_u64_arr())) } } @@ -1608,15 +1512,15 @@ impl G1GetFp for ArkG1 { #[repr(C)] #[derive(Debug, Default, PartialEq, Eq, Clone, Copy)] -pub struct ArkG1Affine (pub blst_p1_affine); +pub struct ArkG1Affine { + pub aff: G1Affine, +} impl G1AffineTrait for ArkG1Affine { fn into_affine(g1: &ArkG1) -> Self { - let mut ret: Self = Default::default(); - unsafe { - blst::blst_p1_to_affine(&mut ret.0, &g1.0); + Self { + aff: g1.0.into_affine(), } - ret } fn into_affines(g1: &[ArkG1]) -> Vec { @@ -1630,60 +1534,49 @@ impl G1AffineTrait for ArkG1Affine { } fn to_proj(&self) -> ArkG1 { - let mut ret: ArkG1 = Default::default(); - unsafe { - blst::blst_p1_from_affine(&mut ret.0, &self.0); - } - ret + ArkG1(self.aff.into_projective()) } + fn x(&self) -> &ArkFp { unsafe { // Transmute safe due to repr(C) on FsFp - core::mem::transmute(&self.0.x) + core::mem::transmute(&self.aff.x) } } fn y(&self) -> &ArkFp { unsafe { // Transmute safe due to repr(C) on FsFp - core::mem::transmute(&self.0.y) + core::mem::transmute(&self.aff.y) } } fn is_infinity(&self) -> bool { - unsafe { blst::blst_p1_affine_is_inf(&self.0) } + self.aff.infinity } - // fn is_zero(&self) -> bool { - // self.aff.is_zero() - // } - + fn is_zero(&self) -> bool { + self.aff.is_zero() + } + fn zero() -> Self { - Self(blst_p1_affine { - x: { - blst_fp { - l: [0, 0, 0, 0, 0, 0], - } - }, - y: { - blst_fp { - l: [0, 0, 0, 0, 0, 0], - } - }, - }) + Self { + aff: G1Affine::new(ArkFp::zero().0, ArkFp::zero().0, true), + } } + fn x_mut(&mut self) -> &mut ArkFp { unsafe { // Transmute safe due to repr(C) on FsFp - core::mem::transmute(&mut self.0.x) + core::mem::transmute(&mut self.aff.x) } } fn y_mut(&mut self) -> &mut ArkFp { unsafe { // Transmute safe due to repr(C) on FsFp - core::mem::transmute(&mut self.0.y) + core::mem::transmute(&mut self.aff.y) } } } @@ -1691,14 +1584,10 @@ impl G1AffineTrait for ArkG1Affine { pub struct ArkG1ProjAddAffine; impl G1ProjAddAffine for ArkG1ProjAddAffine { fn add_assign_affine(proj: &mut ArkG1, aff: &ArkG1Affine) { - unsafe { - blst::blst_p1_add_affine(&mut proj.0, &proj.0, &aff.0); - } + proj.0.add_assign_mixed(&aff.aff); } fn add_or_double_assign_affine(proj: &mut ArkG1, aff: &ArkG1Affine) { - unsafe { - blst::blst_p1_add_or_double_affine(&mut proj.0, &proj.0, &aff.0); - } + proj.0.add_assign_mixed(&aff.aff); } -} +} \ No newline at end of file diff --git a/arkworks3/src/utils.rs b/arkworks3/src/utils.rs index 3aff5fd7e..36d38d87a 100644 --- a/arkworks3/src/utils.rs +++ b/arkworks3/src/utils.rs @@ -109,19 +109,19 @@ pub(crate) fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result>(), g1_values_lagrange_brp: unsafe { core::slice::from_raw_parts(c_settings.g1_values_lagrange_brp, FIELD_ELEMENTS_PER_BLOB) } .iter() - .map(|r| ArkG1(*r)) + .map(|r| ArkG1::from_blst_p1(*r)) .collect::>(), g2_values_monomial: unsafe { core::slice::from_raw_parts(c_settings.g2_values_monomial, TRUSTED_SETUP_NUM_G2_POINTS) } .iter() - .map(|r| ArkG2(*r)) + .map(|r| ArkG2::from_blst_p2(*r)) .collect::>(), x_ext_fft_columns: unsafe { core::slice::from_raw_parts( @@ -133,7 +133,7 @@ pub(crate) fn kzg_settings_to_rust(c_settings: &CKZGSettings) -> Result>() }) .collect::>(), @@ -177,7 +177,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { rust_settings .g1_values_monomial .iter() - .map(|r| r.0) + .map(|r| r.to_blst_p1()) .collect::>() .into_boxed_slice(), ) @@ -186,7 +186,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { rust_settings .g1_values_lagrange_brp .iter() - .map(|r| r.0) + .map(|r| r.to_blst_p1()) .collect::>() .into_boxed_slice(), ) @@ -195,7 +195,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { rust_settings .g2_values_monomial .iter() - .map(|r| r.0) + .map(|r| r.to_blst_p2()) .collect::>() .into_boxed_slice(), ) @@ -207,7 +207,7 @@ pub(crate) fn kzg_settings_to_c(rust_settings: &LKZGSettings) -> CKZGSettings { .map(|r| { Box::leak( r.iter() - .map(|it| it.0) + .map(|it| it.to_blst_p1()) .collect::>() .into_boxed_slice(), ) From 04cd0e153ba41a481d51fb45ebf795439eeff876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 21 Nov 2024 18:42:51 +0200 Subject: [PATCH 20/21] removed unused imports --- arkworks3/src/kzg_proofs.rs | 4 ---- arkworks3/src/kzg_types.rs | 14 +++----------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index c1ffc9f73..808724397 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -7,10 +7,6 @@ use ark_bls12_381::Bls12_381; use ark_ec::PairingEngine; use alloc::sync::Arc; use ark_ec::ProjectiveCurve; -use blst::{ - blst_fp12_is_one, blst_p1_affine, blst_p1_cneg, blst_p1_to_affine, blst_p2_affine, - blst_p2_to_affine, -}; use ark_std::One; use kzg::eip_4844::hash_to_bls_field; use kzg::msm::precompute::PrecomputationTable; diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index 71baee0bd..d2ccf05b0 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -12,19 +12,11 @@ use ark_ec::{AffineCurve, ModelParameters}; use ark_ec::{models::short_weierstrass_jacobian::GroupProjective, ProjectiveCurve}; use ark_ff::{BigInteger, Field}; use ark_std::{One, Zero}; -use std::ops::{AddAssign, Neg, Sub}; +use std::ops::{AddAssign, Sub}; use blst::{ - blst_bendian_from_scalar, blst_fp, blst_fp2, blst_fr, blst_fr_add, blst_fr_cneg, - blst_fr_eucl_inverse, blst_fr_from_scalar, blst_fr_from_uint64, blst_fr_inverse, blst_fr_mul, - blst_fr_sqr, blst_fr_sub, blst_p1, blst_p1_add, blst_p1_add_or_double, blst_p1_affine, - blst_p1_cneg, blst_p1_compress, blst_p1_double, blst_p1_from_affine, blst_p1_in_g1, - blst_p1_is_equal, blst_p1_is_inf, blst_p1_mult, blst_p1_uncompress, blst_p2, - blst_p2_add_or_double, blst_p2_affine, blst_p2_cneg, blst_p2_compress, blst_p2_double, - blst_p2_from_affine, blst_p2_is_equal, blst_p2_mult, blst_p2_uncompress, blst_scalar, - blst_scalar_fr_check, blst_scalar_from_bendian, blst_scalar_from_fr, blst_uint64_from_fr, - BLST_ERROR, + blst_bendian_from_scalar, blst_fp, blst_fp2, blst_fr, blst_fr_add, blst_fr_cneg, blst_fr_eucl_inverse, blst_fr_from_scalar, blst_fr_from_uint64, blst_fr_inverse, blst_fr_mul, blst_fr_sqr, blst_fr_sub, blst_p1, blst_p1_affine, blst_p1_compress, blst_p1_from_affine, blst_p1_in_g1, blst_p1_uncompress, blst_p2, blst_p2_affine, blst_p2_from_affine, blst_p2_uncompress, blst_scalar, blst_scalar_fr_check, blst_scalar_from_bendian, blst_scalar_from_fr, blst_uint64_from_fr, BLST_ERROR }; -use kzg::common_utils::{log2_u64, log_2_byte, reverse_bit_order}; +use kzg::common_utils::{log2_u64, reverse_bit_order}; use kzg::eip_4844::{ BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, FIELD_ELEMENTS_PER_BLOB, FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS From d14d5b3e88d5cbc0a2195b7c02d7fe055b597c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matas=20=C5=A0varlys?= Date: Thu, 21 Nov 2024 22:23:04 +0200 Subject: [PATCH 21/21] ran cargo fmt --- arkworks3/benches/fk_20.rs | 4 +++- arkworks3/benches/kzg.rs | 4 +++- arkworks3/src/fft_g1.rs | 19 +++++++++++++------ arkworks3/src/kzg_proofs.rs | 4 ++-- arkworks3/src/kzg_types.rs | 31 +++++++++++++++---------------- arkworks3/src/poly.rs | 2 +- arkworks3/tests/eip_4844.rs | 4 +++- arkworks3/tests/fk20_proofs.rs | 4 +++- arkworks3/tests/kzg_proofs.rs | 4 +++- 9 files changed, 46 insertions(+), 30 deletions(-) diff --git a/arkworks3/benches/fk_20.rs b/arkworks3/benches/fk_20.rs index 847c4d97e..8e548bcd7 100644 --- a/arkworks3/benches/fk_20.rs +++ b/arkworks3/benches/fk_20.rs @@ -1,7 +1,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::fk20::{bench_fk_multi_da, bench_fk_single_da}; use rust_kzg_arkworks3::fk20_proofs::{KzgFK20MultiSettings, KzgFK20SingleSettings}; -use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, LFFTSettings as FFTSettings, LKZGSettings as KZGSettings}; +use rust_kzg_arkworks3::kzg_proofs::{ + generate_trusted_setup, 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/kzg.rs b/arkworks3/benches/kzg.rs index 717470710..a6f80ff63 100644 --- a/arkworks3/benches/kzg.rs +++ b/arkworks3/benches/kzg.rs @@ -1,7 +1,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use kzg_bench::benches::kzg::{bench_commit_to_poly, bench_compute_proof_single}; -use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, LFFTSettings as FFTSettings, LKZGSettings as KZGSettings}; +use rust_kzg_arkworks3::kzg_proofs::{ + generate_trusted_setup, 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/src/fft_g1.rs b/arkworks3/src/fft_g1.rs index ee8f76e26..23a1bb332 100644 --- a/arkworks3/src/fft_g1.rs +++ b/arkworks3/src/fft_g1.rs @@ -1,7 +1,7 @@ use crate::kzg_proofs::LFFTSettings; -use crate::kzg_types::{ArkFr, ArkG1}; -use crate::kzg_types::{ArkFp, ArkG1Affine}; use crate::kzg_types::ArkG1ProjAddAffine; +use crate::kzg_types::{ArkFp, ArkG1Affine}; +use crate::kzg_types::{ArkFr, ArkG1}; use kzg::msm::msm_impls::msm; @@ -55,7 +55,7 @@ pub fn g1_linear_combination( points, scalars, len, - precomputation + precomputation, ); } } @@ -146,14 +146,21 @@ pub fn fft_g1_fast( #[cfg(not(feature = "parallel"))] { - fft_g1_fast(&mut ret[..half], data, stride * 2, roots, roots_stride * 2, 1); + fft_g1_fast( + &mut ret[..half], + data, + stride * 2, + roots, + roots_stride * 2, + 1, + ); fft_g1_fast( &mut ret[half..], &data[stride..], stride * 2, roots, roots_stride * 2, - 1 + 1, ); } @@ -165,4 +172,4 @@ pub fn fft_g1_fast( } else { ret[0] = data[0]; } -} \ No newline at end of file +} diff --git a/arkworks3/src/kzg_proofs.rs b/arkworks3/src/kzg_proofs.rs index 808724397..3fb503529 100644 --- a/arkworks3/src/kzg_proofs.rs +++ b/arkworks3/src/kzg_proofs.rs @@ -3,9 +3,9 @@ extern crate alloc; use crate::kzg_types::{ArkFp, ArkFr, ArkG1Affine}; use crate::kzg_types::{ArkFr as BlstFr, ArkG1, ArkG2}; +use alloc::sync::Arc; use ark_bls12_381::Bls12_381; use ark_ec::PairingEngine; -use alloc::sync::Arc; use ark_ec::ProjectiveCurve; use ark_std::One; use kzg::eip_4844::hash_to_bls_field; @@ -83,4 +83,4 @@ pub fn pairings_verify(a1: &ArkG1, a2: &ArkG2, b1: &ArkG1, b2: &ArkG2) -> bool { (ark_b1.into(), ark_b2.into()), ]) .is_one() -} \ No newline at end of file +} diff --git a/arkworks3/src/kzg_types.rs b/arkworks3/src/kzg_types.rs index d2ccf05b0..6e843d9ac 100644 --- a/arkworks3/src/kzg_types.rs +++ b/arkworks3/src/kzg_types.rs @@ -4,28 +4,34 @@ pub use crate::kzg_proofs::{expand_root_of_unity, pairings_verify, LFFTSettings, // use crate::poly::{poly_fast_div, poly_inverse, poly_long_div, poly_mul_direct, poly_mul_fft}; use crate::recover::{scale_poly, unscale_poly}; use crate::utils::{ - blst_fp_into_pc_fq, blst_p1_into_pc_g1projective, blst_p2_into_pc_g2projective, pc_g1projective_into_blst_p1, pc_g2projective_into_blst_p2, PolyData + blst_fp_into_pc_fq, blst_p1_into_pc_g1projective, blst_p2_into_pc_g2projective, + pc_g1projective_into_blst_p1, pc_g2projective_into_blst_p2, PolyData, }; use crate::P2; use ark_bls12_381::{g1, g2, G1Affine}; -use ark_ec::{AffineCurve, ModelParameters}; use ark_ec::{models::short_weierstrass_jacobian::GroupProjective, ProjectiveCurve}; +use ark_ec::{AffineCurve, ModelParameters}; use ark_ff::{BigInteger, Field}; use ark_std::{One, Zero}; -use std::ops::{AddAssign, Sub}; use blst::{ - blst_bendian_from_scalar, blst_fp, blst_fp2, blst_fr, blst_fr_add, blst_fr_cneg, blst_fr_eucl_inverse, blst_fr_from_scalar, blst_fr_from_uint64, blst_fr_inverse, blst_fr_mul, blst_fr_sqr, blst_fr_sub, blst_p1, blst_p1_affine, blst_p1_compress, blst_p1_from_affine, blst_p1_in_g1, blst_p1_uncompress, blst_p2, blst_p2_affine, blst_p2_from_affine, blst_p2_uncompress, blst_scalar, blst_scalar_fr_check, blst_scalar_from_bendian, blst_scalar_from_fr, blst_uint64_from_fr, BLST_ERROR + blst_bendian_from_scalar, blst_fp, blst_fp2, blst_fr, blst_fr_add, blst_fr_cneg, + blst_fr_eucl_inverse, blst_fr_from_scalar, blst_fr_from_uint64, blst_fr_inverse, blst_fr_mul, + blst_fr_sqr, blst_fr_sub, blst_p1, blst_p1_affine, blst_p1_compress, blst_p1_from_affine, + blst_p1_in_g1, blst_p1_uncompress, blst_p2, blst_p2_affine, blst_p2_from_affine, + blst_p2_uncompress, blst_scalar, blst_scalar_fr_check, blst_scalar_from_bendian, + blst_scalar_from_fr, blst_uint64_from_fr, BLST_ERROR, }; use kzg::common_utils::{log2_u64, reverse_bit_order}; use kzg::eip_4844::{ BYTES_PER_FIELD_ELEMENT, BYTES_PER_G1, BYTES_PER_G2, FIELD_ELEMENTS_PER_BLOB, - FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS + FIELD_ELEMENTS_PER_CELL, FIELD_ELEMENTS_PER_EXT_BLOB, TRUSTED_SETUP_NUM_G2_POINTS, }; use kzg::msm::precompute::{precompute, PrecomputationTable}; use kzg::{ FFTFr, FFTSettings, FFTSettingsPoly, Fr as KzgFr, G1Affine as G1AffineTrait, G1Fp, G1GetFp, G1LinComb, G1Mul, G1ProjAddAffine, G2Mul, KZGSettings, PairingVerify, Poly, Scalar256, G1, G2, }; +use std::ops::{AddAssign, Sub}; extern crate alloc; use alloc::sync::Arc; @@ -45,7 +51,6 @@ use alloc::sync::Arc; pub struct ArkFr(pub blst_fr); // impl Fr for ArkFr { - // fn bigint_check_mod_256(a: &[u64; 4]) -> bool { // let (_, overflow) = a[0].overflowing_sub(BLS12_381_MOD_256[0]); @@ -336,7 +341,6 @@ impl G1 for ArkG1 { }) } - fn generator() -> Self { ArkG1::from_blst_p1(blst_p1 { x: blst_fp { @@ -372,7 +376,6 @@ impl G1 for ArkG1 { }) } - fn negative_generator() -> Self { ArkG1::from_blst_p1(blst_p1 { x: blst_fp { @@ -416,7 +419,6 @@ impl G1 for ArkG1 { Self(GroupProjective::rand(&mut rng)) } - #[allow(clippy::bind_instead_of_map)] fn from_bytes(bytes: &[u8]) -> Result { bytes @@ -552,7 +554,8 @@ impl PairingVerify for ArkG1 { } #[repr(C)] -#[derive(Debug, Default, PartialEq, Eq, Clone)]pub struct ArkG2(pub GroupProjective); +#[derive(Debug, Default, PartialEq, Eq, Clone)] +pub struct ArkG2(pub GroupProjective); impl ArkG2 { pub fn from_blst_p2(p2: blst::blst_p2) -> Self { @@ -719,7 +722,6 @@ impl G2 for ArkG2 { }) } - #[allow(clippy::bind_instead_of_map)] fn from_bytes(bytes: &[u8]) -> Result { bytes @@ -749,7 +751,6 @@ impl G2 for ArkG2 { <[u8; 96]>::try_from(self.0.x.c0.0.to_bytes_le()).unwrap() } - fn add_or_dbl(&mut self, b: &Self) -> Self { Self(self.0 + b.0) } @@ -1027,7 +1028,6 @@ impl FFTSettingsPoly for LFFTSettings { } } - impl Default for LFFTSettings { fn default() -> Self { Self { @@ -1529,7 +1529,6 @@ impl G1AffineTrait for ArkG1Affine { ArkG1(self.aff.into_projective()) } - fn x(&self) -> &ArkFp { unsafe { // Transmute safe due to repr(C) on FsFp @@ -1551,7 +1550,7 @@ impl G1AffineTrait for ArkG1Affine { fn is_zero(&self) -> bool { self.aff.is_zero() } - + fn zero() -> Self { Self { aff: G1Affine::new(ArkFp::zero().0, ArkFp::zero().0, true), @@ -1582,4 +1581,4 @@ impl G1ProjAddAffine for ArkG1ProjAddAffine { fn add_or_double_assign_affine(proj: &mut ArkG1, aff: &ArkG1Affine) { proj.0.add_assign_mixed(&aff.aff); } -} \ No newline at end of file +} diff --git a/arkworks3/src/poly.rs b/arkworks3/src/poly.rs index f177c4543..8e3176885 100644 --- a/arkworks3/src/poly.rs +++ b/arkworks3/src/poly.rs @@ -127,4 +127,4 @@ impl PolyData { self.mul_fft(multiplier, output_len) } } -} \ No newline at end of file +} diff --git a/arkworks3/tests/eip_4844.rs b/arkworks3/tests/eip_4844.rs index d0aaf9022..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, LFFTSettings, LKZGSettings as 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; diff --git a/arkworks3/tests/fk20_proofs.rs b/arkworks3/tests/fk20_proofs.rs index 36bdc9686..c4dbf3056 100644 --- a/arkworks3/tests/fk20_proofs.rs +++ b/arkworks3/tests/fk20_proofs.rs @@ -3,7 +3,9 @@ mod tests { use kzg_bench::tests::fk20_proofs::*; use rust_kzg_arkworks3::fk20_proofs::{KzgFK20MultiSettings, KzgFK20SingleSettings}; - use rust_kzg_arkworks3::kzg_proofs::{generate_trusted_setup, LFFTSettings as FFTSettings, LKZGSettings as KZGSettings}; + use rust_kzg_arkworks3::kzg_proofs::{ + generate_trusted_setup, LFFTSettings as FFTSettings, LKZGSettings as KZGSettings, + }; use rust_kzg_arkworks3::kzg_types::{ArkFp, ArkFr as BlstFr, ArkG1Affine}; use rust_kzg_arkworks3::kzg_types::{ArkG1, ArkG2}; use rust_kzg_arkworks3::utils::PolyData; diff --git a/arkworks3/tests/kzg_proofs.rs b/arkworks3/tests/kzg_proofs.rs index 73c19422e..af721f0bd 100644 --- a/arkworks3/tests/kzg_proofs.rs +++ b/arkworks3/tests/kzg_proofs.rs @@ -3,7 +3,9 @@ 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_arkworks3::kzg_proofs::{generate_trusted_setup, LFFTSettings as FFTSettings, LKZGSettings as KZGSettings}; + use rust_kzg_arkworks3::kzg_proofs::{ + generate_trusted_setup, LFFTSettings as FFTSettings, LKZGSettings as KZGSettings, + }; use rust_kzg_arkworks3::kzg_types::{ArkFp, ArkFr, ArkG1, ArkG1Affine, ArkG2}; use rust_kzg_arkworks3::utils::PolyData;