Nova/src/spartan/mod.rs
src/spartan/mod.rsRaw
1//! This module implements RelaxedR1CSSNARKTrait using Spartan that is generic
2//! over the polynomial commitment and evaluation argument (i.e., a PCS)
3//! We provide two implementations, one in snark.rs (which does not use any preprocessing)
4//! and another in ppsnark.rs (which uses preprocessing to keep the verifier's state small if the PCS scheme provides a succinct verifier)
5//! We also provide direct.rs that allows proving a step circuit directly with either of the two SNARKs.
6pub mod direct;
7mod math;
8pub(crate) mod polynomial;
9pub mod ppsnark;
10pub mod snark;
11mod sumcheck;
12
13use crate::{traits::Group, Commitment};
14use ff::Field;
15use polynomial::SparsePolynomial;
16
17fn powers<G: Group>(s: &G::Scalar, n: usize) -> Vec<G::Scalar> {
18 assert!(n >= 1);
19 let mut powers = Vec::new();
20 powers.push(G::Scalar::ONE);
21 for i in 1..n {
22 powers.push(powers[i - 1] * s);
23 }
24 powers
25}
26
27/// A type that holds a witness to a polynomial evaluation instance
28pub struct PolyEvalWitness<G: Group> {
29 p: Vec<G::Scalar>, // polynomial
30}
31
32impl<G: Group> PolyEvalWitness<G> {
33 fn pad(W: &[PolyEvalWitness<G>]) -> Vec<PolyEvalWitness<G>> {
34 // determine the maximum size
35 if let Some(n) = W.iter().map(|w| w.p.len()).max() {
36 W.iter()
37 .map(|w| {
38 let mut p = w.p.clone();
39 p.resize(n, G::Scalar::ZERO);
40 PolyEvalWitness { p }
41 })
42 .collect()
43 } else {
44 Vec::new()
45 }
46 }
47
48 fn weighted_sum(W: &[PolyEvalWitness<G>], s: &[G::Scalar]) -> PolyEvalWitness<G> {
49 assert_eq!(W.len(), s.len());
50 let mut p = vec![G::Scalar::ZERO; W[0].p.len()];
51 for i in 0..W.len() {
52 for j in 0..W[i].p.len() {
53 p[j] += W[i].p[j] * s[i]
54 }
55 }
56 PolyEvalWitness { p }
57 }
58
59 fn batch(p_vec: &[&Vec<G::Scalar>], s: &G::Scalar) -> PolyEvalWitness<G> {
60 let powers_of_s = powers::<G>(s, p_vec.len());
61 let mut p = vec![G::Scalar::ZERO; p_vec[0].len()];
62 for i in 0..p_vec.len() {
63 for (j, item) in p.iter_mut().enumerate().take(p_vec[i].len()) {
64 *item += p_vec[i][j] * powers_of_s[i]
65 }
66 }
67 PolyEvalWitness { p }
68 }
69}
70
71/// A type that holds a polynomial evaluation instance
72pub struct PolyEvalInstance<G: Group> {
73 c: Commitment<G>, // commitment to the polynomial
74 x: Vec<G::Scalar>, // evaluation point
75 e: G::Scalar, // claimed evaluation
76}
77
78impl<G: Group> PolyEvalInstance<G> {
79 fn pad(U: &[PolyEvalInstance<G>]) -> Vec<PolyEvalInstance<G>> {
80 // determine the maximum size
81 if let Some(ell) = U.iter().map(|u| u.x.len()).max() {
82 U.iter()
83 .map(|u| {
84 let mut x = vec![G::Scalar::ZERO; ell - u.x.len()];
85 x.extend(u.x.clone());
86 PolyEvalInstance { c: u.c, x, e: u.e }
87 })
88 .collect()
89 } else {
90 Vec::new()
91 }
92 }
93
94 fn batch(
95 c_vec: &[Commitment<G>],
96 x: &[G::Scalar],
97 e_vec: &[G::Scalar],
98 s: &G::Scalar,
99 ) -> PolyEvalInstance<G> {
100 let powers_of_s = powers::<G>(s, c_vec.len());
101 let e = e_vec
102 .iter()
103 .zip(powers_of_s.iter())
104 .map(|(e, p)| *e * p)
105 .sum();
106 let c = c_vec
107 .iter()
108 .zip(powers_of_s.iter())
109 .map(|(c, p)| *c * *p)
110 .fold(Commitment::<G>::default(), |acc, item| acc + item);
111
112 PolyEvalInstance {
113 c,
114 x: x.to_vec(),
115 e,
116 }
117 }
118}