ark_poly_commit/marlin/marlin_pc/
mod.rs

1use crate::{
2    kzg10, marlin::Marlin, BTreeMap, BTreeSet, BatchLCProof, Error, Evaluations, LabeledCommitment,
3    LabeledPolynomial, LinearCombination, PCCommitmentState, PCCommitterKey, PCUniversalParams,
4    PolynomialCommitment, QuerySet, CHALLENGE_SIZE,
5};
6use ark_crypto_primitives::sponge::CryptographicSponge;
7use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup};
8use ark_ff::Zero;
9use ark_poly::DenseUVPolynomial;
10use ark_std::{marker::PhantomData, ops::Div, rand::RngCore};
11#[cfg(not(feature = "std"))]
12use ark_std::{string::ToString, vec::Vec};
13
14mod data_structures;
15pub use data_structures::*;
16
17/// Polynomial commitment based on [[KZG10]][kzg], with degree enforcement, batching,
18/// and (optional) hiding property taken from [[CHMMVW20, “Marlin”]][marlin].
19///
20/// Degree bound enforcement requires that (at least one of) the points at
21/// which a committed polynomial is evaluated are from a distribution that is
22/// random conditioned on the polynomial. This is because degree bound
23/// enforcement relies on checking a polynomial identity at this point.
24/// More formally, the points must be sampled from an admissible query sampler,
25/// as detailed in [[CHMMVW20]][marlin].
26///
27/// [kzg]: http://cacr.uwaterloo.ca/techreports/2010/cacr2010-10.pdf
28/// [marlin]: https://eprint.iacr.org/2019/1047
29pub struct MarlinKZG10<E: Pairing, P: DenseUVPolynomial<E::ScalarField>> {
30    _engine: PhantomData<E>,
31    _poly: PhantomData<P>,
32}
33
34pub(crate) fn shift_polynomial<E: Pairing, P: DenseUVPolynomial<E::ScalarField>>(
35    ck: &CommitterKey<E>,
36    p: &P,
37    degree_bound: usize,
38) -> P {
39    if p.is_zero() {
40        P::zero()
41    } else {
42        let enforced_degree_bounds = ck
43            .enforced_degree_bounds
44            .as_ref()
45            .expect("Polynomial requires degree bounds, but `ck` does not support any");
46        let largest_enforced_degree_bound = enforced_degree_bounds.last().unwrap();
47
48        let mut shifted_polynomial_coeffs =
49            vec![E::ScalarField::zero(); largest_enforced_degree_bound - degree_bound];
50        shifted_polynomial_coeffs.extend_from_slice(&p.coeffs());
51        P::from_coefficients_vec(shifted_polynomial_coeffs)
52    }
53}
54
55impl<E, P> PolynomialCommitment<E::ScalarField, P> for MarlinKZG10<E, P>
56where
57    E: Pairing,
58    P: DenseUVPolynomial<E::ScalarField, Point = E::ScalarField>,
59    for<'a, 'b> &'a P: Div<&'b P, Output = P>,
60{
61    type UniversalParams = UniversalParams<E>;
62    type CommitterKey = CommitterKey<E>;
63    type VerifierKey = VerifierKey<E>;
64    type Commitment = Commitment<E>;
65    type CommitmentState = Randomness<E::ScalarField, P>;
66    type Proof = kzg10::Proof<E>;
67    type BatchProof = Vec<Self::Proof>;
68    type Error = Error;
69
70    /// Constructs public parameters when given as input the maximum degree `max_degree`
71    /// for the polynomial commitment scheme.
72    fn setup<R: RngCore>(
73        max_degree: usize,
74        _num_vars: Option<usize>,
75        rng: &mut R,
76    ) -> Result<Self::UniversalParams, Self::Error> {
77        kzg10::KZG10::setup(max_degree, false, rng).map_err(Into::into)
78    }
79
80    fn trim(
81        pp: &Self::UniversalParams,
82        supported_degree: usize,
83        supported_hiding_bound: usize,
84        enforced_degree_bounds: Option<&[usize]>,
85    ) -> Result<(Self::CommitterKey, Self::VerifierKey), Self::Error> {
86        let max_degree = pp.max_degree();
87        if supported_degree > max_degree {
88            return Err(Error::TrimmingDegreeTooLarge);
89        }
90
91        // Construct the KZG10 committer key for committing to unshifted polynomials.
92        let ck_time = start_timer!(|| format!(
93            "Constructing `powers` of size {} for unshifted polys",
94            supported_degree
95        ));
96        let powers = pp.powers_of_g[..=supported_degree].to_vec();
97        // We want to support making up to `supported_hiding_bound` queries to committed
98        // polynomials.
99        let powers_of_gamma_g = (0..=supported_hiding_bound + 1)
100            .map(|i| pp.powers_of_gamma_g[&i])
101            .collect::<Vec<_>>();
102
103        end_timer!(ck_time);
104
105        // Construct the core KZG10 verifier key.
106        let vk = kzg10::VerifierKey {
107            g: pp.powers_of_g[0].clone(),
108            gamma_g: pp.powers_of_gamma_g[&0],
109            h: pp.h.clone(),
110            beta_h: pp.beta_h.clone(),
111            prepared_h: pp.prepared_h.clone(),
112            prepared_beta_h: pp.prepared_beta_h.clone(),
113        };
114
115        let enforced_degree_bounds = enforced_degree_bounds.map(|v| {
116            let mut v = v.to_vec();
117            v.sort();
118            v.dedup();
119            v
120        });
121
122        // Check whether we have some degree bounds to enforce
123        let (shifted_powers, degree_bounds_and_shift_powers) =
124            if let Some(enforced_degree_bounds) = enforced_degree_bounds.as_ref() {
125                if enforced_degree_bounds.is_empty() {
126                    (None, None)
127                } else {
128                    let mut sorted_enforced_degree_bounds = enforced_degree_bounds.clone();
129                    sorted_enforced_degree_bounds.sort();
130
131                    let lowest_shifted_power = max_degree
132                        - sorted_enforced_degree_bounds
133                            .last()
134                            .ok_or(Error::EmptyDegreeBounds)?;
135
136                    let shifted_ck_time = start_timer!(|| format!(
137                        "Constructing `shifted_powers` of size {}",
138                        max_degree - lowest_shifted_power + 1
139                    ));
140
141                    let shifted_powers = pp.powers_of_g[lowest_shifted_power..].to_vec();
142                    end_timer!(shifted_ck_time);
143
144                    let degree_bounds_and_shift_powers = enforced_degree_bounds
145                        .iter()
146                        .map(|d| (*d, pp.powers_of_g[max_degree - *d]))
147                        .collect();
148                    (Some(shifted_powers), Some(degree_bounds_and_shift_powers))
149                }
150            } else {
151                (None, None)
152            };
153
154        let ck = CommitterKey {
155            powers,
156            shifted_powers,
157            powers_of_gamma_g,
158            enforced_degree_bounds: enforced_degree_bounds,
159            max_degree,
160        };
161
162        let vk = VerifierKey {
163            vk,
164            degree_bounds_and_shift_powers,
165            supported_degree,
166            max_degree,
167        };
168        Ok((ck, vk))
169    }
170
171    /// Outputs a commitment to `polynomial`.
172    fn commit<'a>(
173        ck: &Self::CommitterKey,
174        polynomials: impl IntoIterator<Item = &'a LabeledPolynomial<E::ScalarField, P>>,
175        rng: Option<&mut dyn RngCore>,
176    ) -> Result<
177        (
178            Vec<LabeledCommitment<Self::Commitment>>,
179            Vec<Self::CommitmentState>,
180        ),
181        Self::Error,
182    >
183    where
184        P: 'a,
185    {
186        let rng = &mut crate::optional_rng::OptionalRng(rng);
187        let commit_time = start_timer!(|| "Committing to polynomials");
188
189        let mut commitments = Vec::new();
190        let mut states = Vec::new();
191
192        for p in polynomials {
193            let label = p.label();
194            let degree_bound = p.degree_bound();
195            let hiding_bound = p.hiding_bound();
196            let polynomial: &P = p.polynomial();
197
198            let enforced_degree_bounds: Option<&[usize]> = ck
199                .enforced_degree_bounds
200                .as_ref()
201                .map(|bounds| bounds.as_slice());
202            kzg10::KZG10::<E, P>::check_degrees_and_bounds(
203                ck.supported_degree(),
204                ck.max_degree,
205                enforced_degree_bounds,
206                &p,
207            )?;
208
209            let commit_time = start_timer!(|| format!(
210                "Polynomial {} of degree {}, degree bound {:?}, and hiding bound {:?}",
211                label,
212                polynomial.degree(),
213                degree_bound,
214                hiding_bound,
215            ));
216
217            let (comm, rand) =
218                kzg10::KZG10::commit(&ck.powers(), polynomial, hiding_bound, Some(rng))?;
219            let (shifted_comm, shifted_rand) = if let Some(degree_bound) = degree_bound {
220                let shifted_powers = ck
221                    .shifted_powers(degree_bound)
222                    .ok_or(Error::UnsupportedDegreeBound(degree_bound))?;
223                let (shifted_comm, shifted_rand) =
224                    kzg10::KZG10::commit(&shifted_powers, &polynomial, hiding_bound, Some(rng))?;
225                (Some(shifted_comm), Some(shifted_rand))
226            } else {
227                (None, None)
228            };
229
230            let comm = Commitment { comm, shifted_comm };
231            let state = Randomness { rand, shifted_rand };
232            commitments.push(LabeledCommitment::new(
233                label.to_string(),
234                comm,
235                degree_bound,
236            ));
237            states.push(state);
238            end_timer!(commit_time);
239        }
240        end_timer!(commit_time);
241        Ok((commitments, states))
242    }
243
244    /// On input a polynomial `p` and a point `point`, outputs a proof for the same.
245    fn open<'a>(
246        ck: &Self::CommitterKey,
247        labeled_polynomials: impl IntoIterator<Item = &'a LabeledPolynomial<E::ScalarField, P>>,
248        _commitments: impl IntoIterator<Item = &'a LabeledCommitment<Self::Commitment>>,
249        point: &'a P::Point,
250        sponge: &mut impl CryptographicSponge,
251        states: impl IntoIterator<Item = &'a Self::CommitmentState>,
252        _rng: Option<&mut dyn RngCore>,
253    ) -> Result<Self::Proof, Self::Error>
254    where
255        P: 'a,
256        Self::CommitmentState: 'a,
257        Self::Commitment: 'a,
258    {
259        let mut p = P::zero();
260        let mut r = kzg10::Randomness::empty();
261        let mut shifted_w = P::zero();
262        let mut shifted_r = kzg10::Randomness::empty();
263        let mut shifted_r_witness = P::zero();
264
265        let mut enforce_degree_bound = false;
266        for (polynomial, rand) in labeled_polynomials.into_iter().zip(states) {
267            let degree_bound = polynomial.degree_bound();
268            assert_eq!(degree_bound.is_some(), rand.shifted_rand.is_some());
269
270            let enforced_degree_bounds: Option<&[usize]> = ck
271                .enforced_degree_bounds
272                .as_ref()
273                .map(|bounds| bounds.as_slice());
274            kzg10::KZG10::<E, P>::check_degrees_and_bounds(
275                ck.supported_degree(),
276                ck.max_degree,
277                enforced_degree_bounds,
278                &polynomial,
279            )?;
280
281            // compute next challenges challenge^j and challenge^{j+1}.
282            let challenge_j = sponge.squeeze_field_elements_with_sizes(&[CHALLENGE_SIZE])[0];
283
284            assert_eq!(degree_bound.is_some(), rand.shifted_rand.is_some());
285
286            p += (challenge_j, polynomial.polynomial());
287            r += (challenge_j, &rand.rand);
288
289            if let Some(degree_bound) = degree_bound {
290                enforce_degree_bound = true;
291                let shifted_rand = rand.shifted_rand.as_ref().unwrap();
292                let (witness, shifted_rand_witness) =
293                    kzg10::KZG10::<E, P>::compute_witness_polynomial(
294                        polynomial.polynomial(),
295                        *point,
296                        &shifted_rand,
297                    )?;
298                let challenge_j_1 = sponge.squeeze_field_elements_with_sizes(&[CHALLENGE_SIZE])[0];
299
300                let shifted_witness = shift_polynomial(ck, &witness, degree_bound);
301
302                shifted_w += (challenge_j_1, &shifted_witness);
303                shifted_r += (challenge_j_1, shifted_rand);
304                if let Some(shifted_rand_witness) = shifted_rand_witness {
305                    shifted_r_witness += (challenge_j_1, &shifted_rand_witness);
306                }
307            }
308        }
309        let proof_time = start_timer!(|| "Creating proof for unshifted polynomials");
310        let proof = kzg10::KZG10::open(&ck.powers(), &p, *point, &r)?;
311        let mut w = proof.w.into_group();
312        let mut random_v = proof.random_v;
313        end_timer!(proof_time);
314
315        if enforce_degree_bound {
316            let proof_time = start_timer!(|| "Creating proof for shifted polynomials");
317            let shifted_proof = kzg10::KZG10::open_with_witness_polynomial(
318                &ck.shifted_powers(None).unwrap(),
319                *point,
320                &shifted_r,
321                &shifted_w,
322                Some(&shifted_r_witness),
323            )?;
324            end_timer!(proof_time);
325
326            w += &shifted_proof.w.into_group();
327            if let Some(shifted_random_v) = shifted_proof.random_v {
328                random_v = random_v.map(|v| v + &shifted_random_v);
329            }
330        }
331
332        Ok(kzg10::Proof {
333            w: w.into_affine(),
334            random_v,
335        })
336    }
337
338    /// Verifies that `value` is the evaluation at `x` of the polynomial
339    /// committed inside `comm`.
340    fn check<'a>(
341        vk: &Self::VerifierKey,
342        commitments: impl IntoIterator<Item = &'a LabeledCommitment<Self::Commitment>>,
343        point: &'a P::Point,
344        values: impl IntoIterator<Item = E::ScalarField>,
345        proof: &Self::Proof,
346        sponge: &mut impl CryptographicSponge,
347        _rng: Option<&mut dyn RngCore>,
348    ) -> Result<bool, Self::Error>
349    where
350        Self::Commitment: 'a,
351    {
352        let check_time = start_timer!(|| "Checking evaluations");
353        let (combined_comm, combined_value) =
354            Marlin::<E, P, Self>::accumulate_commitments_and_values(
355                commitments,
356                values,
357                sponge,
358                Some(vk),
359            )?;
360        let combined_comm = kzg10::Commitment(combined_comm.into());
361        let result = kzg10::KZG10::check(&vk.vk, &combined_comm, *point, combined_value, proof)?;
362        end_timer!(check_time);
363        Ok(result)
364    }
365
366    fn batch_check<'a, R: RngCore>(
367        vk: &Self::VerifierKey,
368        commitments: impl IntoIterator<Item = &'a LabeledCommitment<Self::Commitment>>,
369        query_set: &QuerySet<P::Point>,
370        values: &Evaluations<E::ScalarField, P::Point>,
371        proof: &Self::BatchProof,
372        sponge: &mut impl CryptographicSponge,
373        rng: &mut R,
374    ) -> Result<bool, Self::Error>
375    where
376        Self::Commitment: 'a,
377    {
378        let (combined_comms, combined_queries, combined_evals) =
379            Marlin::<E, P, Self>::combine_and_normalize(
380                commitments,
381                query_set,
382                values,
383                sponge,
384                Some(vk),
385            )?;
386        assert_eq!(proof.len(), combined_queries.len());
387        let proof_time = start_timer!(|| "Checking KZG10::Proof");
388        let result = kzg10::KZG10::batch_check(
389            &vk.vk,
390            &combined_comms,
391            &combined_queries,
392            &combined_evals,
393            &proof,
394            rng,
395        )?;
396        end_timer!(proof_time);
397        Ok(result)
398    }
399
400    fn open_combinations<'a>(
401        ck: &Self::CommitterKey,
402        lc_s: impl IntoIterator<Item = &'a LinearCombination<E::ScalarField>>,
403        polynomials: impl IntoIterator<Item = &'a LabeledPolynomial<E::ScalarField, P>>,
404        commitments: impl IntoIterator<Item = &'a LabeledCommitment<Self::Commitment>>,
405        query_set: &QuerySet<P::Point>,
406        sponge: &mut impl CryptographicSponge,
407        states: impl IntoIterator<Item = &'a Self::CommitmentState>,
408        rng: Option<&mut dyn RngCore>,
409    ) -> Result<BatchLCProof<E::ScalarField, Self::BatchProof>, Self::Error>
410    where
411        P: 'a,
412        Self::CommitmentState: 'a,
413        Self::Commitment: 'a,
414    {
415        Marlin::<E, P, Self>::open_combinations(
416            ck,
417            lc_s,
418            polynomials,
419            commitments,
420            query_set,
421            sponge,
422            states,
423            rng,
424        )
425    }
426
427    /// Checks that `values` are the true evaluations at `query_set` of the polynomials
428    /// committed in `labeled_commitments`.
429    fn check_combinations<'a, R: RngCore>(
430        vk: &Self::VerifierKey,
431        lc_s: impl IntoIterator<Item = &'a LinearCombination<E::ScalarField>>,
432        commitments: impl IntoIterator<Item = &'a LabeledCommitment<Self::Commitment>>,
433        query_set: &QuerySet<P::Point>,
434        evaluations: &Evaluations<E::ScalarField, P::Point>,
435        proof: &BatchLCProof<E::ScalarField, Self::BatchProof>,
436        sponge: &mut impl CryptographicSponge,
437        rng: &mut R,
438    ) -> Result<bool, Self::Error>
439    where
440        Self::Commitment: 'a,
441    {
442        Marlin::<E, P, Self>::check_combinations(
443            vk,
444            lc_s,
445            commitments,
446            query_set,
447            evaluations,
448            proof,
449            sponge,
450            rng,
451        )
452    }
453
454    /// On input a list of labeled polynomials and a query set, `open` outputs a proof of evaluation
455    /// of the polynomials at the points in the query set.
456    fn batch_open<'a>(
457        ck: &CommitterKey<E>,
458        labeled_polynomials: impl IntoIterator<Item = &'a LabeledPolynomial<E::ScalarField, P>>,
459        commitments: impl IntoIterator<Item = &'a LabeledCommitment<Commitment<E>>>,
460        query_set: &QuerySet<P::Point>,
461        sponge: &mut impl CryptographicSponge,
462        states: impl IntoIterator<Item = &'a Self::CommitmentState>,
463        rng: Option<&mut dyn RngCore>,
464    ) -> Result<Vec<kzg10::Proof<E>>, Error>
465    where
466        P: 'a,
467        Self::CommitmentState: 'a,
468        Self::Commitment: 'a,
469    {
470        let rng = &mut crate::optional_rng::OptionalRng(rng);
471        let poly_rand_comm: BTreeMap<_, _> = labeled_polynomials
472            .into_iter()
473            .zip(states)
474            .zip(commitments.into_iter())
475            .map(|((poly, r), comm)| (poly.label(), (poly, r, comm)))
476            .collect();
477
478        let open_time = start_timer!(|| format!(
479            "Opening {} polynomials at query set of size {}",
480            poly_rand_comm.len(),
481            query_set.len(),
482        ));
483
484        let mut query_to_labels_map = BTreeMap::new();
485
486        for (label, (point_label, point)) in query_set.iter() {
487            let labels = query_to_labels_map
488                .entry(point_label)
489                .or_insert((point, BTreeSet::new()));
490            labels.1.insert(label);
491        }
492
493        let mut proofs = Vec::new();
494        for (_point_label, (point, labels)) in query_to_labels_map.into_iter() {
495            let mut query_polys: Vec<&'a LabeledPolynomial<_, _>> = Vec::new();
496            let mut query_states: Vec<&'a Self::CommitmentState> = Vec::new();
497            let mut query_comms: Vec<&'a LabeledCommitment<Self::Commitment>> = Vec::new();
498
499            for label in labels {
500                let (polynomial, rand, comm) =
501                    poly_rand_comm.get(&label).ok_or(Error::MissingPolynomial {
502                        label: label.to_string(),
503                    })?;
504
505                query_polys.push(polynomial);
506                query_states.push(rand);
507                query_comms.push(comm);
508            }
509
510            let proof_time = start_timer!(|| "Creating proof");
511            let proof = Self::open(
512                ck,
513                query_polys,
514                query_comms,
515                point,
516                sponge,
517                query_states,
518                Some(rng),
519            )?;
520
521            end_timer!(proof_time);
522
523            proofs.push(proof);
524        }
525        end_timer!(open_time);
526
527        Ok(proofs.into())
528    }
529}
530
531#[cfg(test)]
532mod tests {
533    #![allow(non_camel_case_types)]
534    use super::MarlinKZG10;
535    use ark_bls12_377::Bls12_377;
536    use ark_bls12_381::Bls12_381;
537    use ark_ec::pairing::Pairing;
538    use ark_ff::UniformRand;
539    use ark_poly::{univariate::DensePolynomial as DensePoly, DenseUVPolynomial};
540    use rand_chacha::ChaCha20Rng;
541
542    type UniPoly_381 = DensePoly<<Bls12_381 as Pairing>::ScalarField>;
543    type UniPoly_377 = DensePoly<<Bls12_377 as Pairing>::ScalarField>;
544
545    type PC<E, P> = MarlinKZG10<E, P>;
546
547    type PC_Bls12_381 = PC<Bls12_381, UniPoly_381>;
548    type PC_Bls12_377 = PC<Bls12_377, UniPoly_377>;
549
550    fn rand_poly<E: Pairing>(
551        degree: usize,
552        _: Option<usize>,
553        rng: &mut ChaCha20Rng,
554    ) -> DensePoly<E::ScalarField> {
555        DensePoly::<E::ScalarField>::rand(degree, rng)
556    }
557
558    fn constant_poly<E: Pairing>(
559        _: usize,
560        _: Option<usize>,
561        rng: &mut ChaCha20Rng,
562    ) -> DensePoly<E::ScalarField> {
563        DensePoly::<E::ScalarField>::from_coefficients_slice(&[E::ScalarField::rand(rng)])
564    }
565
566    fn rand_point<E: Pairing>(_: Option<usize>, rng: &mut ChaCha20Rng) -> E::ScalarField {
567        E::ScalarField::rand(rng)
568    }
569
570    #[test]
571    fn single_poly_test() {
572        use crate::tests::*;
573        single_poly_test::<_, _, PC_Bls12_377, _>(
574            None,
575            rand_poly::<Bls12_377>,
576            rand_point::<Bls12_377>,
577            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
578        )
579        .expect("test failed for bls12-377");
580        single_poly_test::<_, _, PC_Bls12_381, _>(
581            None,
582            rand_poly::<Bls12_381>,
583            rand_point::<Bls12_381>,
584            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
585        )
586        .expect("test failed for bls12-381");
587    }
588
589    #[test]
590    fn constant_poly_test() {
591        use crate::tests::*;
592        single_poly_test::<_, _, PC_Bls12_377, _>(
593            None,
594            constant_poly::<Bls12_377>,
595            rand_point::<Bls12_377>,
596            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
597        )
598        .expect("test failed for bls12-377");
599        single_poly_test::<_, _, PC_Bls12_381, _>(
600            None,
601            constant_poly::<Bls12_381>,
602            rand_point::<Bls12_381>,
603            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
604        )
605        .expect("test failed for bls12-381");
606    }
607
608    #[test]
609    fn quadratic_poly_degree_bound_multiple_queries_test() {
610        use crate::tests::*;
611        quadratic_poly_degree_bound_multiple_queries_test::<_, _, PC_Bls12_377, _>(
612            rand_poly::<Bls12_377>,
613            rand_point::<Bls12_377>,
614            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
615        )
616        .expect("test failed for bls12-377");
617        quadratic_poly_degree_bound_multiple_queries_test::<_, _, PC_Bls12_381, _>(
618            rand_poly::<Bls12_381>,
619            rand_point::<Bls12_381>,
620            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
621        )
622        .expect("test failed for bls12-381");
623    }
624
625    #[test]
626    fn linear_poly_degree_bound_test() {
627        use crate::tests::*;
628        linear_poly_degree_bound_test::<_, _, PC_Bls12_377, _>(
629            rand_poly::<Bls12_377>,
630            rand_point::<Bls12_377>,
631            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
632        )
633        .expect("test failed for bls12-377");
634        linear_poly_degree_bound_test::<_, _, PC_Bls12_381, _>(
635            rand_poly::<Bls12_381>,
636            rand_point::<Bls12_381>,
637            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
638        )
639        .expect("test failed for bls12-381");
640    }
641
642    #[test]
643    fn single_poly_degree_bound_test() {
644        use crate::tests::*;
645        single_poly_degree_bound_test::<_, _, PC_Bls12_377, _>(
646            rand_poly::<Bls12_377>,
647            rand_point::<Bls12_377>,
648            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
649        )
650        .expect("test failed for bls12-377");
651        single_poly_degree_bound_test::<_, _, PC_Bls12_381, _>(
652            rand_poly::<Bls12_381>,
653            rand_point::<Bls12_381>,
654            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
655        )
656        .expect("test failed for bls12-381");
657    }
658
659    #[test]
660    fn single_poly_degree_bound_multiple_queries_test() {
661        use crate::tests::*;
662        single_poly_degree_bound_multiple_queries_test::<_, _, PC_Bls12_377, _>(
663            rand_poly::<Bls12_377>,
664            rand_point::<Bls12_377>,
665            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
666        )
667        .expect("test failed for bls12-377");
668        single_poly_degree_bound_multiple_queries_test::<_, _, PC_Bls12_381, _>(
669            rand_poly::<Bls12_381>,
670            rand_point::<Bls12_381>,
671            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
672        )
673        .expect("test failed for bls12-381");
674    }
675
676    #[test]
677    fn two_polys_degree_bound_single_query_test() {
678        use crate::tests::*;
679        two_polys_degree_bound_single_query_test::<_, _, PC_Bls12_377, _>(
680            rand_poly::<Bls12_377>,
681            rand_point::<Bls12_377>,
682            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
683        )
684        .expect("test failed for bls12-377");
685        two_polys_degree_bound_single_query_test::<_, _, PC_Bls12_381, _>(
686            rand_poly::<Bls12_381>,
687            rand_point::<Bls12_381>,
688            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
689        )
690        .expect("test failed for bls12-381");
691    }
692
693    #[test]
694    fn full_end_to_end_test() {
695        use crate::tests::*;
696        full_end_to_end_test::<_, _, PC_Bls12_377, _>(
697            None,
698            rand_poly::<Bls12_377>,
699            rand_point::<Bls12_377>,
700            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
701        )
702        .expect("test failed for bls12-377");
703        println!("Finished bls12-377");
704        full_end_to_end_test::<_, _, PC_Bls12_381, _>(
705            None,
706            rand_poly::<Bls12_381>,
707            rand_point::<Bls12_381>,
708            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
709        )
710        .expect("test failed for bls12-381");
711        println!("Finished bls12-381");
712    }
713
714    #[test]
715    fn single_equation_test() {
716        use crate::tests::*;
717        single_equation_test::<_, _, PC_Bls12_377, _>(
718            None,
719            rand_poly::<Bls12_377>,
720            rand_point::<Bls12_377>,
721            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
722        )
723        .expect("test failed for bls12-377");
724        println!("Finished bls12-377");
725        single_equation_test::<_, _, PC_Bls12_381, _>(
726            None,
727            rand_poly::<Bls12_381>,
728            rand_point::<Bls12_381>,
729            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
730        )
731        .expect("test failed for bls12-381");
732        println!("Finished bls12-381");
733    }
734
735    #[test]
736    fn two_equation_test() {
737        use crate::tests::*;
738        two_equation_test::<_, _, PC_Bls12_377, _>(
739            None,
740            rand_poly::<Bls12_377>,
741            rand_point::<Bls12_377>,
742            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
743        )
744        .expect("test failed for bls12-377");
745        println!("Finished bls12-377");
746        two_equation_test::<_, _, PC_Bls12_381, _>(
747            None,
748            rand_poly::<Bls12_381>,
749            rand_point::<Bls12_381>,
750            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
751        )
752        .expect("test failed for bls12-381");
753        println!("Finished bls12-381");
754    }
755
756    #[test]
757    fn two_equation_degree_bound_test() {
758        use crate::tests::*;
759        two_equation_degree_bound_test::<_, _, PC_Bls12_377, _>(
760            rand_poly::<Bls12_377>,
761            rand_point::<Bls12_377>,
762            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
763        )
764        .expect("test failed for bls12-377");
765        println!("Finished bls12-377");
766        two_equation_degree_bound_test::<_, _, PC_Bls12_381, _>(
767            rand_poly::<Bls12_381>,
768            rand_point::<Bls12_381>,
769            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
770        )
771        .expect("test failed for bls12-381");
772        println!("Finished bls12-381");
773    }
774
775    #[test]
776    fn full_end_to_end_equation_test() {
777        use crate::tests::*;
778        full_end_to_end_equation_test::<_, _, PC_Bls12_377, _>(
779            None,
780            rand_poly::<Bls12_377>,
781            rand_point::<Bls12_377>,
782            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
783        )
784        .expect("test failed for bls12-377");
785        println!("Finished bls12-377");
786        full_end_to_end_equation_test::<_, _, PC_Bls12_381, _>(
787            None,
788            rand_poly::<Bls12_381>,
789            rand_point::<Bls12_381>,
790            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
791        )
792        .expect("test failed for bls12-381");
793        println!("Finished bls12-381");
794    }
795
796    #[test]
797    #[should_panic]
798    fn bad_degree_bound_test() {
799        use crate::tests::*;
800        bad_degree_bound_test::<_, _, PC_Bls12_377, _>(
801            rand_poly::<Bls12_377>,
802            rand_point::<Bls12_377>,
803            poseidon_sponge_for_test::<<Bls12_377 as Pairing>::ScalarField>,
804        )
805        .expect("test failed for bls12-377");
806        println!("Finished bls12-377");
807        bad_degree_bound_test::<_, _, PC_Bls12_381, _>(
808            rand_poly::<Bls12_381>,
809            rand_point::<Bls12_381>,
810            poseidon_sponge_for_test::<<Bls12_381 as Pairing>::ScalarField>,
811        )
812        .expect("test failed for bls12-381");
813        println!("Finished bls12-381");
814    }
815}