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}