//! This module implements RelaxedR1CSSNARKTrait using Spartan that is generic //! over the polynomial commitment and evaluation argument (i.e., a PCS) //! We provide two implementations, one in snark.rs (which does not use any preprocessing) //! and another in ppsnark.rs (which uses preprocessing to keep the verifier's state small if the PCS scheme provides a succinct verifier) //! We also provide direct.rs that allows proving a step circuit directly with either of the two SNARKs. pub mod direct; mod math; pub(crate) mod polynomial; pub mod ppsnark; pub mod snark; mod sumcheck; use crate::{traits::Group, Commitment}; use ff::Field; use polynomial::SparsePolynomial; fn powers(s: &G::Scalar, n: usize) -> Vec { assert!(n >= 1); let mut powers = Vec::new(); powers.push(G::Scalar::ONE); for i in 1..n { powers.push(powers[i - 1] * s); } powers } /// A type that holds a witness to a polynomial evaluation instance pub struct PolyEvalWitness { p: Vec, // polynomial } impl PolyEvalWitness { fn pad(W: &[PolyEvalWitness]) -> Vec> { // determine the maximum size if let Some(n) = W.iter().map(|w| w.p.len()).max() { W.iter() .map(|w| { let mut p = w.p.clone(); p.resize(n, G::Scalar::ZERO); PolyEvalWitness { p } }) .collect() } else { Vec::new() } } fn weighted_sum(W: &[PolyEvalWitness], s: &[G::Scalar]) -> PolyEvalWitness { assert_eq!(W.len(), s.len()); let mut p = vec![G::Scalar::ZERO; W[0].p.len()]; for i in 0..W.len() { for j in 0..W[i].p.len() { p[j] += W[i].p[j] * s[i] } } PolyEvalWitness { p } } fn batch(p_vec: &[&Vec], s: &G::Scalar) -> PolyEvalWitness { let powers_of_s = powers::(s, p_vec.len()); let mut p = vec![G::Scalar::ZERO; p_vec[0].len()]; for i in 0..p_vec.len() { for (j, item) in p.iter_mut().enumerate().take(p_vec[i].len()) { *item += p_vec[i][j] * powers_of_s[i] } } PolyEvalWitness { p } } } /// A type that holds a polynomial evaluation instance pub struct PolyEvalInstance { c: Commitment, // commitment to the polynomial x: Vec, // evaluation point e: G::Scalar, // claimed evaluation } impl PolyEvalInstance { fn pad(U: &[PolyEvalInstance]) -> Vec> { // determine the maximum size if let Some(ell) = U.iter().map(|u| u.x.len()).max() { U.iter() .map(|u| { let mut x = vec![G::Scalar::ZERO; ell - u.x.len()]; x.extend(u.x.clone()); PolyEvalInstance { c: u.c, x, e: u.e } }) .collect() } else { Vec::new() } } fn batch( c_vec: &[Commitment], x: &[G::Scalar], e_vec: &[G::Scalar], s: &G::Scalar, ) -> PolyEvalInstance { let powers_of_s = powers::(s, c_vec.len()); let e = e_vec .iter() .zip(powers_of_s.iter()) .map(|(e, p)| *e * p) .sum(); let c = c_vec .iter() .zip(powers_of_s.iter()) .map(|(c, p)| *c * *p) .fold(Commitment::::default(), |acc, item| acc + item); PolyEvalInstance { c, x: x.to_vec(), e, } } }