1#![cfg_attr(not(feature = "std"), no_std)]
10#![deny(missing_docs)]
11#[cfg(test)]
12extern crate std;
13
14#[cfg(any(not(feature = "std"), target_has_atomic = "ptr"))]
15#[doc(hidden)]
16extern crate alloc;
17
18pub mod errors;
19pub mod multilinear_kzg;
20mod poly;
21pub mod prelude;
22mod structs;
23mod toeplitz;
24pub mod transcript;
25pub mod univariate_kzg;
26
27pub use errors::PCSError;
28
29use ark_ff::{FftField, Field};
30use ark_poly::{EvaluationDomain, Radix2EvaluationDomain};
31use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
32use ark_std::{
33 borrow::Borrow,
34 cmp,
35 fmt::Debug,
36 hash::Hash,
37 rand::{CryptoRng, RngCore},
38 vec::Vec,
39};
40
41pub trait PolynomialCommitmentScheme {
45 type SRS: Clone + Debug + StructuredReferenceString;
47 type Polynomial: Clone + Debug + Hash + PartialEq + Eq;
49 type Point: Clone + Ord + Debug + Sync + Hash + PartialEq + Eq;
51 type Evaluation: Field;
53 type Commitment: Clone
55 + CanonicalSerialize
56 + CanonicalDeserialize
57 + Debug
58 + PartialEq
59 + Eq
60 + Hash;
61 type BatchCommitment: Clone + CanonicalSerialize + CanonicalDeserialize + Debug + PartialEq + Eq;
63 type Proof: Clone + CanonicalSerialize + CanonicalDeserialize + Debug + PartialEq + Eq + Hash;
65 type BatchProof: Clone + CanonicalSerialize + CanonicalDeserialize + Debug + PartialEq + Eq;
67
68 #[cfg(any(test, feature = "test-srs"))]
77 fn gen_srs_for_testing<R: RngCore + CryptoRng>(
78 rng: &mut R,
79 supported_degree: usize,
80 ) -> Result<Self::SRS, PCSError> {
81 Self::SRS::gen_srs_for_testing(rng, supported_degree)
82 }
83
84 #[cfg(any(test, feature = "test-srs"))]
94 fn gen_srs_for_testing_with_verifier_degree<R: RngCore + CryptoRng>(
95 rng: &mut R,
96 prover_supported_degree: usize,
97 verifier_supported_degree: usize,
98 ) -> Result<Self::SRS, PCSError> {
99 Self::SRS::gen_srs_for_testing_with_verifier_degree(
100 rng,
101 prover_supported_degree,
102 verifier_supported_degree,
103 )
104 }
105
106 fn load_srs_from_file(
113 supported_degree: usize,
114 file: Option<&str>,
115 ) -> Result<Self::SRS, PCSError> {
116 Self::SRS::load_srs_from_file(supported_degree, file)
117 }
118
119 #[allow(clippy::type_complexity)]
130 fn trim(
131 srs: impl Borrow<Self::SRS>,
132 supported_degree: usize,
133 supported_num_vars: Option<usize>,
134 ) -> Result<
135 (
136 <Self::SRS as StructuredReferenceString>::ProverParam,
137 <Self::SRS as StructuredReferenceString>::VerifierParam,
138 ),
139 PCSError,
140 >;
141
142 fn commit(
144 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
145 poly: &Self::Polynomial,
146 ) -> Result<Self::Commitment, PCSError>;
147
148 fn batch_commit(
150 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
151 polys: &[Self::Polynomial],
152 ) -> Result<Self::BatchCommitment, PCSError>;
153
154 fn open(
157 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
158 polynomial: &Self::Polynomial,
159 point: &Self::Point,
160 ) -> Result<(Self::Proof, Self::Evaluation), PCSError>;
161
162 fn batch_open(
165 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
166 batch_commitment: &Self::BatchCommitment,
167 polynomials: &[Self::Polynomial],
168 points: &[Self::Point],
169 ) -> Result<(Self::BatchProof, Vec<Self::Evaluation>), PCSError>;
170
171 #[allow(clippy::type_complexity)]
174 fn multi_open(
175 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
176 polynomial: &Self::Polynomial,
177 points: &[Self::Point],
178 ) -> Result<(Vec<Self::Proof>, Vec<Self::Evaluation>), PCSError> {
179 Ok(points
180 .iter()
181 .map(|point| Self::open(prover_param.borrow(), polynomial, point))
182 .collect::<Result<Vec<_>, _>>()?
183 .into_iter()
184 .unzip())
185 }
186
187 fn verify(
190 verifier_param: &<Self::SRS as StructuredReferenceString>::VerifierParam,
191 commitment: &Self::Commitment,
192 point: &Self::Point,
193 value: &Self::Evaluation,
194 proof: &Self::Proof,
195 ) -> Result<bool, PCSError>;
196
197 fn batch_verify<R: RngCore + CryptoRng>(
200 verifier_param: &<Self::SRS as StructuredReferenceString>::VerifierParam,
201 multi_commitment: &Self::BatchCommitment,
202 points: &[Self::Point],
203 values: &[Self::Evaluation],
204 batch_proof: &Self::BatchProof,
205 rng: &mut R,
206 ) -> Result<bool, PCSError>;
207}
208
209pub trait StructuredReferenceString: Sized {
211 type ProverParam;
213 type VerifierParam;
215
216 fn extract_prover_param(&self, supported_degree: usize) -> Self::ProverParam;
218 fn extract_verifier_param(&self, supported_degree: usize) -> Self::VerifierParam;
220
221 fn trim(
231 &self,
232 supported_degree: usize,
233 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError>;
234
235 fn trim_with_verifier_degree(
246 &self,
247 prover_supported_degree: usize,
248 verifier_supported_degree: usize,
249 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError>;
250
251 #[cfg(any(test, feature = "test-srs"))]
260 fn gen_srs_for_testing<R: RngCore + CryptoRng>(
261 rng: &mut R,
262 supported_degree: usize,
263 ) -> Result<Self, PCSError>;
264
265 #[cfg(any(test, feature = "test-srs"))]
275 fn gen_srs_for_testing_with_verifier_degree<R: RngCore + CryptoRng>(
276 rng: &mut R,
277 prover_supported_degree: usize,
278 verifier_supported_degree: usize,
279 ) -> Result<Self, PCSError>;
280
281 fn load_srs_from_file(_supported_degree: usize, _file: Option<&str>) -> Result<Self, PCSError> {
288 unimplemented!("TODO: implement loading SRS from files");
289 }
290}
291
292pub trait UnivariatePCS: PolynomialCommitmentScheme
294where
295 Self::Evaluation: FftField,
296{
297 #[allow(clippy::type_complexity)]
301 fn trim_fft_size(
302 srs: impl Borrow<Self::SRS>,
303 supported_degree: usize,
304 ) -> Result<
305 (
306 <Self::SRS as StructuredReferenceString>::ProverParam,
307 <Self::SRS as StructuredReferenceString>::VerifierParam,
308 ),
309 PCSError,
310 > {
311 let fft_degree = checked_fft_size(supported_degree)?;
312 srs.borrow().trim(fft_degree).map_err(|e| {
313 PCSError::InvalidParameters(ark_std::format!(
314 "Requesting degree of {} for FFT:\n\t\t{:?}",
315 fft_degree,
316 e
317 ))
318 })
319 }
320
321 fn multi_open_rou_eval_domain(
325 degree: usize,
326 num_points: usize,
327 ) -> Result<Radix2EvaluationDomain<Self::Evaluation>, PCSError> {
328 let padded_degree = checked_fft_size(degree)?;
330
331 let domain_size = cmp::max(padded_degree + 1, num_points);
332 let domain = Radix2EvaluationDomain::new(domain_size).ok_or_else(|| {
333 PCSError::UpstreamError(ark_std::format!(
334 "Fail to init eval domain of size {}",
335 domain_size
336 ))
337 })?;
338
339 Ok(domain)
340 }
341
342 #[allow(clippy::type_complexity)]
346 fn multi_open_rou(
347 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
348 polynomial: &Self::Polynomial,
349 num_points: usize,
350 domain: &Radix2EvaluationDomain<Self::Evaluation>,
351 ) -> Result<(Vec<Self::Proof>, Vec<Self::Evaluation>), PCSError> {
352 let evals = Self::multi_open_rou_evals(polynomial, num_points, domain)?;
353 let proofs = Self::multi_open_rou_proofs(prover_param, polynomial, num_points, domain)?;
354 Ok((proofs, evals))
355 }
356
357 fn multi_open_rou_proofs(
359 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
360 polynomial: &Self::Polynomial,
361 num_points: usize,
362 domain: &Radix2EvaluationDomain<Self::Evaluation>,
363 ) -> Result<Vec<Self::Proof>, PCSError>;
364
365 fn multi_open_rou_evals(
367 polynomial: &Self::Polynomial,
368 num_points: usize,
369 domain: &Radix2EvaluationDomain<Self::Evaluation>,
370 ) -> Result<Vec<Self::Evaluation>, PCSError>;
371
372 fn multi_point_open(
376 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
377 polynomial: &Self::Polynomial,
378 points: &[Self::Point],
379 ) -> Result<(Self::Proof, Vec<Self::Evaluation>), PCSError>;
380
381 fn multi_point_verify(
384 verifier_param: impl Borrow<<Self::SRS as StructuredReferenceString>::VerifierParam>,
385 commitment: &Self::Commitment,
386 points: &[Self::Point],
387 values: &[Self::Evaluation],
388 proof: &Self::Proof,
389 ) -> Result<bool, PCSError>;
390}
391
392#[inline]
394pub fn checked_fft_size(degree: usize) -> Result<usize, PCSError> {
395 let err = || {
396 PCSError::InvalidParameters(ark_std::format!(
397 "Next power of two overflows! Got: {}",
398 degree
399 ))
400 };
401 if degree.is_power_of_two() {
402 degree.checked_mul(2).ok_or_else(err)
403 } else {
404 degree.checked_next_power_of_two().ok_or_else(err)
405 }
406}
407
408#[cfg(feature = "icicle")]
410pub mod icicle_deps {
411 use anyhow::anyhow;
412 pub use icicle_core::{
413 curve::{Affine as IcicleAffine, Curve as IcicleCurve, Projective as IcicleProjective},
414 msm::{MSMConfig, MSM},
415 };
416 pub use icicle_cuda_runtime::{memory::HostOrDeviceSlice, stream::CudaStream};
417
418 pub mod curves {
421 pub use ark_bn254::Bn254;
422 pub use icicle_bn254::curve::CurveCfg as IcicleBn254;
423 }
424
425 pub use crate::univariate_kzg::icicle::GPUCommittable;
426
427 pub fn warmup_new_stream() -> anyhow::Result<CudaStream> {
431 let stream = CudaStream::create().map_err(|e| anyhow!("{:?}", e))?;
432 let _warmup_bytes = HostOrDeviceSlice::<'_, u8>::cuda_malloc_async(1024, &stream)
433 .map_err(|e| anyhow!("{:?}", e))?;
434 Ok(stream)
435 }
436}