Skip to main content

zinc_piop/ideal_check/
batched_ideal_check.rs

1use crypto_primitives::SetConfig;
2#[cfg(feature = "parallel")]
3use rayon::prelude::*;
4use thiserror::Error;
5use zinc_uair::ideal::{Ideal, IdealCheck, IdealCheckError};
6use zinc_utils::cfg_iter;
7
8/// Checks if the collected ideals contain a slice
9/// of elements `values`. Returns an error if the
10/// lengths mismatch or if any of the `values`
11/// does not belong to the corresponding ideal.
12pub fn batched_ideal_check<C: SetConfig, I: Ideal + IdealCheck<C>>(
13    cfg: &C,
14    ideals: &[I],
15    values: &[C::Element],
16) -> Result<(), BatchedIdealCheckError<C::Element>> {
17    if ideals.len() != values.len() {
18        return Err(BatchedIdealCheckError::LengthMismatch {
19            num_ideals: ideals.len(),
20            provided_values: values.len(),
21        });
22    }
23
24    cfg_iter!(ideals)
25        .zip(cfg_iter!(values))
26        .try_for_each(|(ideal, value)| {
27            if !ideal.contains(cfg, value)? {
28                Err(BatchedIdealCheckError::NotInIdeal(
29                    value.clone(),
30                    ideal.to_string(),
31                ))
32            } else {
33                Ok(())
34            }
35        })
36}
37
38#[derive(Clone, Debug, Error)]
39pub enum BatchedIdealCheckError<R> {
40    #[error(
41        "length mismatch: the collector has {num_ideals} ideals, provided {provided_values} values to check"
42    )]
43    LengthMismatch {
44        num_ideals: usize,
45        provided_values: usize,
46    },
47    #[error("{0} does not belong to the ideal {1}")]
48    NotInIdeal(R, String),
49    #[error("Ideal check failed: {}", 0.0)]
50    IdealCheckFailed(#[from] IdealCheckError),
51}