From 90ddc9562555c616ff870b78c76c144f49101140 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Mon, 2 Oct 2023 13:51:44 +0200 Subject: [PATCH 1/3] Moved back to parallel for build proof --- kate/src/com.rs | 87 ++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/kate/src/com.rs b/kate/src/com.rs index 608e30c6..03367ef1 100644 --- a/kate/src/com.rs +++ b/kate/src/com.rs @@ -374,49 +374,62 @@ pub fn build_proof( let total_start = Instant::now(); // attempt to parallelly compute proof for all requested cells - let cell_iter = cells.iter().zip(result_bytes.chunks_exact_mut(SPROOF_SIZE)); + let cell_iter = cells + .into_par_iter() + .zip(result_bytes.par_chunks_exact_mut(SPROOF_SIZE)); - for (cell, res) in cell_iter { - let r_index = usize::try_from(cell.row.0)?; + cell_iter.for_each(|(cell, res)| { + let Ok(r_index) = usize::try_from(cell.row.0) else { + res.fill(0); + return; + }; if r_index >= ext_rows || cell.col >= block_dims.cols { - return Err(Error::IndexOutOfRange); - } else { - let c_index = usize::try_from(cell.col.0)?; - let get_ext_data_matrix = - |j: usize| ext_data_matrix[r_index.saturating_add(j.saturating_mul(ext_rows))]; - - // construct polynomial per extended matrix row - #[cfg(feature = "parallel")] - let row = { - let mut row = - Vec::with_capacity(ext_cols.checked_add(1).ok_or(Error::BlockTooBig)?); - (0..ext_cols) - .into_par_iter() - .map(get_ext_data_matrix) - .collect_into_vec(&mut row); - row - }; - #[cfg(not(feature = "parallel"))] - let row = (0..ext_cols) - .map(get_ext_data_matrix) - .collect::>(); + res.fill(0); + return; + } - // row has to be a power of 2, otherwise interpolate() function panics TODO: cache evaluations - let poly = Evaluations::from_vec_and_domain(row, row_eval_domain).interpolate(); - let witness = prover_key.compute_single_witness(&poly, &row_dom_x_pts[c_index]); + let Ok(c_index) = usize::try_from(cell.col.0) else { + res.fill(0); + return; + }; - match prover_key.commit(&witness) { - Ok(commitment_to_witness) => { - let evaluated_point = - ext_data_matrix[r_index.saturating_add(c_index.saturating_mul(ext_rows))]; + let get_ext_data_matrix = + |j: usize| ext_data_matrix[r_index.saturating_add(j.saturating_mul(ext_rows))]; - res[0..PROOF_SIZE].copy_from_slice(&commitment_to_witness.to_bytes()); - res[PROOF_SIZE..].copy_from_slice(&evaluated_point.to_bytes()); - }, - Err(e) => return Err(Error::PlonkError(e)), + // construct polynomial per extended matrix row + #[cfg(feature = "parallel")] + let row: Vec = { + let Some(capacity) = ext_cols.checked_add(1) else { + res.fill(0); + return; }; - } - } + let mut row = Vec::with_capacity(capacity); + (0..ext_cols) + .into_par_iter() + .map(get_ext_data_matrix) + .collect_into_vec(&mut row); + row + }; + #[cfg(not(feature = "parallel"))] + let row = (0..ext_cols) + .map(get_ext_data_matrix) + .collect::>(); + + // row has to be a power of 2, otherwise interpolate() function panics TODO: cache evaluations + let poly = Evaluations::from_vec_and_domain(row, row_eval_domain).interpolate(); + let witness = prover_key.compute_single_witness(&poly, &row_dom_x_pts[c_index]); + + match prover_key.commit(&witness) { + Ok(commitment_to_witness) => { + let evaluated_point = + ext_data_matrix[r_index.saturating_add(c_index.saturating_mul(ext_rows))]; + + res[0..PROOF_SIZE].copy_from_slice(&commitment_to_witness.to_bytes()); + res[PROOF_SIZE..].copy_from_slice(&evaluated_point.to_bytes()); + }, + Err(_) => res.fill(0), + }; + }); metrics.proof_build_time(total_start.elapsed(), cells.len().saturated_into()); From 6c24f3cbd94ecacdc70c124a0b82f6485ea10b8d Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Mon, 2 Oct 2023 15:02:47 +0200 Subject: [PATCH 2/3] Added missing error handling --- kate/src/com.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/kate/src/com.rs b/kate/src/com.rs index 03367ef1..255d56e5 100644 --- a/kate/src/com.rs +++ b/kate/src/com.rs @@ -3,6 +3,7 @@ use std::{ convert::{TryFrom, TryInto}, mem::size_of, num::TryFromIntError, + sync::Mutex, time::Instant, }; @@ -75,6 +76,7 @@ pub enum Error { /// The extended grid width does not fit cleanly into a domain for FFTs ExtendedGridDomianSizeInvalid(usize), IndexOutOfRange, + ConversionFailed, } impl From for Error { @@ -370,7 +372,6 @@ pub fn build_proof( let prover_key = &prover_key; let row_dom_x_pts = &row_dom_x_pts; - // generate proof only for requested cells let total_start = Instant::now(); // attempt to parallelly compute proof for all requested cells @@ -378,18 +379,25 @@ pub fn build_proof( .into_par_iter() .zip(result_bytes.par_chunks_exact_mut(SPROOF_SIZE)); + let locked_errors = Mutex::new(Vec::::new()); cell_iter.for_each(|(cell, res)| { let Ok(r_index) = usize::try_from(cell.row.0) else { - res.fill(0); + if let Ok(mut errors) = locked_errors.lock() { + errors.push(Error::ConversionFailed) + } return; }; if r_index >= ext_rows || cell.col >= block_dims.cols { - res.fill(0); + if let Ok(mut errors) = locked_errors.lock() { + errors.push(Error::IndexOutOfRange) + } return; } let Ok(c_index) = usize::try_from(cell.col.0) else { - res.fill(0); + if let Ok(mut errors) = locked_errors.lock() { + errors.push(Error::ConversionFailed) + } return; }; @@ -400,7 +408,9 @@ pub fn build_proof( #[cfg(feature = "parallel")] let row: Vec = { let Some(capacity) = ext_cols.checked_add(1) else { - res.fill(0); + if let Ok(mut errors) = locked_errors.lock() { + errors.push(Error::BlockTooBig) + }; return; }; let mut row = Vec::with_capacity(capacity); @@ -427,12 +437,22 @@ pub fn build_proof( res[0..PROOF_SIZE].copy_from_slice(&commitment_to_witness.to_bytes()); res[PROOF_SIZE..].copy_from_slice(&evaluated_point.to_bytes()); }, - Err(_) => res.fill(0), + Err(e) => { + if let Ok(mut errors) = locked_errors.lock() { + errors.push(Error::PlonkError(e)) + } + }, }; }); metrics.proof_build_time(total_start.elapsed(), cells.len().saturated_into()); + if let Ok(mut errors) = locked_errors.lock() { + if let Some(error) = errors.pop() { + return Err(error); + } + } + Ok(result_bytes) } From cf958f7d4e9be45a287f2a6ff1f4db4fe568e088 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Mon, 2 Oct 2023 15:28:15 +0200 Subject: [PATCH 3/3] Refactored code --- kate/src/com.rs | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/kate/src/com.rs b/kate/src/com.rs index 255d56e5..5f258ee5 100644 --- a/kate/src/com.rs +++ b/kate/src/com.rs @@ -380,26 +380,13 @@ pub fn build_proof( .zip(result_bytes.par_chunks_exact_mut(SPROOF_SIZE)); let locked_errors = Mutex::new(Vec::::new()); - cell_iter.for_each(|(cell, res)| { - let Ok(r_index) = usize::try_from(cell.row.0) else { - if let Ok(mut errors) = locked_errors.lock() { - errors.push(Error::ConversionFailed) - } - return; - }; + + let get_cell_row = |cell: &Cell| -> Result<(Vec, usize, usize), Error> { + let r_index = usize::try_from(cell.row.0)?; if r_index >= ext_rows || cell.col >= block_dims.cols { - if let Ok(mut errors) = locked_errors.lock() { - errors.push(Error::IndexOutOfRange) - } - return; + return Err(Error::IndexOutOfRange); } - - let Ok(c_index) = usize::try_from(cell.col.0) else { - if let Ok(mut errors) = locked_errors.lock() { - errors.push(Error::ConversionFailed) - } - return; - }; + let c_index = usize::try_from(cell.col.0)?; let get_ext_data_matrix = |j: usize| ext_data_matrix[r_index.saturating_add(j.saturating_mul(ext_rows))]; @@ -407,13 +394,7 @@ pub fn build_proof( // construct polynomial per extended matrix row #[cfg(feature = "parallel")] let row: Vec = { - let Some(capacity) = ext_cols.checked_add(1) else { - if let Ok(mut errors) = locked_errors.lock() { - errors.push(Error::BlockTooBig) - }; - return; - }; - let mut row = Vec::with_capacity(capacity); + let mut row = Vec::with_capacity(ext_cols.checked_add(1).ok_or(Error::BlockTooBig)?); (0..ext_cols) .into_par_iter() .map(get_ext_data_matrix) @@ -425,6 +406,18 @@ pub fn build_proof( .map(get_ext_data_matrix) .collect::>(); + Ok((row, r_index, c_index)) + }; + + cell_iter.for_each(|(cell, res)| { + let result = get_cell_row(cell); + let Ok((row, r_index, c_index)) = result else { + if let Ok(mut errors) = locked_errors.lock() { + errors.push(result.err().expect("We checked before that this is OK. ")) + } + return; + }; + // row has to be a power of 2, otherwise interpolate() function panics TODO: cache evaluations let poly = Evaluations::from_vec_and_domain(row, row_eval_domain).interpolate(); let witness = prover_key.compute_single_witness(&poly, &row_dom_x_pts[c_index]);