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