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}