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