Skip to main content

poly_commitment/
lib.rs

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