poly_commitment/lib.rs
1mod combine;
2pub mod commitment;
3pub mod error;
4pub mod hash_map_cache;
5pub mod ipa;
6pub mod kzg;
7pub mod precomputed_srs;
8pub mod utils;
9
10// Exposing property based tests for the SRS trait
11pub mod pbt_srs;
12
13pub use commitment::PolyComm;
14
15use crate::{
16 commitment::{BatchEvaluationProof, BlindedCommitment, CommitmentCurve},
17 error::CommitmentError,
18 utils::DensePolynomialOrEvaluations,
19};
20use ark_ec::AffineRepr;
21use ark_ff::UniformRand;
22use ark_poly::{
23 univariate::DensePolynomial, EvaluationDomain, Evaluations, Radix2EvaluationDomain as D,
24};
25use mina_poseidon::FqSponge;
26use rand_core::{CryptoRng, RngCore};
27
28pub trait SRS<G: CommitmentCurve>: Clone + Sized + Sync + Send {
29 /// The maximum polynomial degree that can be committed to
30 fn max_poly_size(&self) -> usize;
31
32 /// Get the group element used for blinding commitments
33 fn blinding_commitment(&self) -> G;
34
35 /// Same as [SRS::mask] except that you can pass the blinders manually.
36 /// A [BlindedCommitment] object is returned instead of a PolyComm object to
37 /// keep the blinding factors and the commitment together. The blinded
38 /// commitment is saved in the commitment field of the output.
39 /// The output is wrapped into a [Result] to handle the case the blinders
40 /// are not the same length than the number of chunks commitments have.
41 fn mask_custom(
42 &self,
43 com: PolyComm<G>,
44 blinders: &PolyComm<G::ScalarField>,
45 ) -> Result<BlindedCommitment<G>, CommitmentError>;
46
47 /// Turns a non-hiding polynomial commitment into a hidding polynomial
48 /// commitment. Transforms each given `<a, G>` into `(<a, G> + wH, w)` with
49 /// a random `w` per commitment.
50 /// A [BlindedCommitment] object is returned instead of a PolyComm object to
51 /// keep the blinding factors and the commitment together. The blinded
52 /// commitment is saved in the commitment field of the output.
53 fn mask(
54 &self,
55 comm: PolyComm<G>,
56 rng: &mut (impl RngCore + CryptoRng),
57 ) -> BlindedCommitment<G> {
58 let blinders = comm.map(|_| G::ScalarField::rand(rng));
59 self.mask_custom(comm, &blinders).unwrap()
60 }
61
62 /// This function commits a polynomial using the SRS' basis of size `n`.
63 /// - `plnm`: polynomial to commit to. The polynomial can be of any degree,
64 /// including higher than `n`.
65 /// - `num_chunks`: the minimal number of commitments to be included in the
66 /// output polynomial commitment.
67 ///
68 /// The function returns the commitments to the chunks (of size at most `n`) of
69 /// the polynomials.
70 ///
71 /// The function will also pad with zeroes if the polynomial has a degree
72 /// smaller than `n * num_chunks`.
73 ///
74 /// Note that if the polynomial has a degree higher than `n * num_chunks`,
75 /// the output will contain more than `num_chunks` commitments as it will
76 /// also contain the additional chunks.
77 ///
78 /// See the test
79 /// [crate::pbt_srs::test_regression_commit_non_hiding_expected_number_of_chunks]
80 /// for an example of the number of chunks returned.
81 fn commit_non_hiding(
82 &self,
83 plnm: &DensePolynomial<G::ScalarField>,
84 num_chunks: usize,
85 ) -> PolyComm<G>;
86
87 /// Commits a polynomial, potentially splitting the result in multiple
88 /// commitments.
89 /// It is analogous to [SRS::commit_evaluations] but for polynomials.
90 /// A [BlindedCommitment] object is returned instead of a PolyComm object to
91 /// keep the blinding factors and the commitment together. The blinded
92 /// commitment is saved in the commitment field of the output.
93 fn commit(
94 &self,
95 plnm: &DensePolynomial<G::ScalarField>,
96 num_chunks: usize,
97 rng: &mut (impl RngCore + CryptoRng),
98 ) -> BlindedCommitment<G>;
99
100 /// Commit to a polynomial, with custom blinding factors.
101 /// It is a combination of [SRS::commit] and [SRS::mask_custom].
102 /// It is analogous to [SRS::commit_evaluations_custom] but for polynomials.
103 /// A [BlindedCommitment] object is returned instead of a PolyComm object to
104 /// keep the blinding factors and the commitment together. The blinded
105 /// commitment is saved in the commitment field of the output.
106 /// The output is wrapped into a [Result] to handle the case the blinders
107 /// are not the same length than the number of chunks commitments have.
108 fn commit_custom(
109 &self,
110 plnm: &DensePolynomial<G::ScalarField>,
111 num_chunks: usize,
112 blinders: &PolyComm<G::ScalarField>,
113 ) -> Result<BlindedCommitment<G>, CommitmentError>;
114
115 /// Commit to evaluations, without blinding factors.
116 /// It is analogous to [SRS::commit_non_hiding] but for evaluations.
117 fn commit_evaluations_non_hiding(
118 &self,
119 domain: D<G::ScalarField>,
120 plnm: &Evaluations<G::ScalarField, D<G::ScalarField>>,
121 ) -> PolyComm<G>;
122
123 /// Commit to evaluations with blinding factors, generated using the random
124 /// number generator `rng`.
125 /// It is analogous to [SRS::commit] but for evaluations.
126 /// A [BlindedCommitment] object is returned instead of a PolyComm object to
127 /// keep the blinding factors and the commitment together. The blinded
128 /// commitment is saved in the commitment field of the output.
129 fn commit_evaluations(
130 &self,
131 domain: D<G::ScalarField>,
132 plnm: &Evaluations<G::ScalarField, D<G::ScalarField>>,
133 rng: &mut (impl RngCore + CryptoRng),
134 ) -> BlindedCommitment<G>;
135
136 /// Commit to evaluations with custom blinding factors.
137 /// It is a combination of [SRS::commit_evaluations] and [SRS::mask_custom].
138 /// It is analogous to [SRS::commit_custom] but for evaluations.
139 /// A [BlindedCommitment] object is returned instead of a PolyComm object to
140 /// keep the blinding factors and the commitment together. The blinded
141 /// commitment is saved in the commitment field of the output.
142 /// The output is wrapped into a [Result] to handle the case the blinders
143 /// are not the same length than the number of chunks commitments have.
144 fn commit_evaluations_custom(
145 &self,
146 domain: D<G::ScalarField>,
147 plnm: &Evaluations<G::ScalarField, D<G::ScalarField>>,
148 blinders: &PolyComm<G::ScalarField>,
149 ) -> Result<BlindedCommitment<G>, CommitmentError>;
150
151 /// Create an SRS of size `depth`.
152 ///
153 /// Warning: in the case of a trusted setup, as it is required for a
154 /// polynomial commitment scheme like KZG, a toxic waste is generated using
155 /// `rand::thread_rng()`. This is not the behavior you would expect in a
156 /// production environment.
157 /// However, we do accept this behavior for the sake of simplicity in the
158 /// interface, and this method will only be supposed to be used in tests in
159 /// this case.
160 fn create(depth: usize) -> Self;
161
162 /// Compute commitments to the lagrange basis corresponding to the given domain and
163 /// cache them in the SRS
164 fn get_lagrange_basis(&self, domain: D<G::ScalarField>) -> &Vec<PolyComm<G>>;
165
166 /// Same as `get_lagrange_basis` but only using the domain size.
167 fn get_lagrange_basis_from_domain_size(&self, domain_size: usize) -> &Vec<PolyComm<G>>;
168
169 fn size(&self) -> usize;
170}
171
172#[allow(type_alias_bounds)]
173/// An alias to represent a polynomial (in either coefficient or
174/// evaluation form), with a set of *scalar field* elements that
175/// represent the exponent of its blinder.
176// TODO: add a string to name the polynomial
177type PolynomialsToCombine<'a, G: CommitmentCurve, D: EvaluationDomain<G::ScalarField>> = &'a [(
178 DensePolynomialOrEvaluations<'a, G::ScalarField, D>,
179 PolyComm<G::ScalarField>,
180)];
181
182pub trait OpenProof<G: CommitmentCurve>: Sized + Clone {
183 type SRS: SRS<G> + std::fmt::Debug;
184
185 /// Create an opening proof for a batch of polynomials. The parameters are
186 /// the following:
187 /// - `srs`: the structured reference string used to commit
188 /// to the polynomials
189 /// - `group_map`: the group map
190 /// - `plnms`: the list of polynomials to open, with possible blinders.
191 /// The type is simply an alias to handle the polynomials in evaluations or
192 /// coefficients forms.
193 /// - `elm`: the evaluation points
194 /// - `polyscale`: a challenge to bacth the polynomials.
195 /// - `evalscale`: a challenge to bacth the evaluation points
196 /// - `sponge`: Sponge used to coin and absorb values and simulate
197 /// non-interactivity using the Fiat-Shamir transformation.
198 /// - `rng`: a pseudo random number generator used for zero-knowledge
199 #[allow(clippy::too_many_arguments)]
200 fn open<EFqSponge, RNG, D: EvaluationDomain<<G as AffineRepr>::ScalarField>>(
201 srs: &Self::SRS,
202 group_map: &<G as CommitmentCurve>::Map,
203 plnms: PolynomialsToCombine<G, D>,
204 elm: &[<G as AffineRepr>::ScalarField],
205 polyscale: <G as AffineRepr>::ScalarField,
206 evalscale: <G as AffineRepr>::ScalarField,
207 sponge: EFqSponge,
208 rng: &mut RNG,
209 ) -> Self
210 where
211 EFqSponge:
212 Clone + FqSponge<<G as AffineRepr>::BaseField, G, <G as AffineRepr>::ScalarField>,
213 RNG: RngCore + CryptoRng;
214
215 /// Verify the opening proof
216 fn verify<EFqSponge, RNG>(
217 srs: &Self::SRS,
218 group_map: &G::Map,
219 batch: &mut [BatchEvaluationProof<G, EFqSponge, Self>],
220 rng: &mut RNG,
221 ) -> bool
222 where
223 EFqSponge: FqSponge<G::BaseField, G, G::ScalarField>,
224 RNG: RngCore + CryptoRng;
225}