1#![cfg_attr(not(feature = "std"), no_std)]
10#![allow(warnings)]
12#![deny(missing_docs)]
13#[cfg(test)]
14extern crate std;
15
16#[macro_use]
17extern crate derivative;
18
19#[cfg(any(not(feature = "std"), target_has_atomic = "ptr"))]
20#[doc(hidden)]
21extern crate alloc;
22
23pub mod errors;
24pub mod multilinear_kzg;
25mod poly;
26pub mod prelude;
27mod structs;
28mod toeplitz;
29pub mod transcript;
30pub mod univariate_kzg;
31
32pub use errors::PCSError;
33
34use ark_ff::{FftField, Field};
35use ark_poly::{EvaluationDomain, Radix2EvaluationDomain};
36use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
37use ark_std::{
38 borrow::Borrow,
39 cmp,
40 fmt::Debug,
41 hash::Hash,
42 rand::{CryptoRng, RngCore},
43 vec::Vec,
44};
45
46pub trait PolynomialCommitmentScheme {
50 type SRS: Clone + Debug + StructuredReferenceString;
52 type Polynomial: Clone + Debug + Hash + PartialEq + Eq;
54 type Point: Clone + Ord + Debug + Sync + Hash + PartialEq + Eq;
56 type Evaluation: Field;
58 type Commitment: Clone
60 + CanonicalSerialize
61 + CanonicalDeserialize
62 + Debug
63 + PartialEq
64 + Eq
65 + Hash;
66 type BatchCommitment: Clone + CanonicalSerialize + CanonicalDeserialize + Debug + PartialEq + Eq;
68 type Proof: Clone + CanonicalSerialize + CanonicalDeserialize + Debug + PartialEq + Eq + Hash;
70 type BatchProof: Clone + CanonicalSerialize + CanonicalDeserialize + Debug + PartialEq + Eq;
72
73 #[cfg(any(test, feature = "test-srs"))]
82 fn gen_srs_for_testing<R: RngCore + CryptoRng>(
83 rng: &mut R,
84 supported_degree: usize,
85 ) -> Result<Self::SRS, PCSError> {
86 Self::SRS::gen_srs_for_testing(rng, supported_degree)
87 }
88
89 #[cfg(any(test, feature = "test-srs"))]
99 fn gen_srs_for_testing_with_verifier_degree<R: RngCore + CryptoRng>(
100 rng: &mut R,
101 prover_supported_degree: usize,
102 verifier_supported_degree: usize,
103 ) -> Result<Self::SRS, PCSError> {
104 Self::SRS::gen_srs_for_testing_with_verifier_degree(
105 rng,
106 prover_supported_degree,
107 verifier_supported_degree,
108 )
109 }
110
111 fn load_srs_from_file(
118 supported_degree: usize,
119 file: Option<&str>,
120 ) -> Result<Self::SRS, PCSError> {
121 Self::SRS::load_srs_from_file(supported_degree, file)
122 }
123
124 #[allow(clippy::type_complexity)]
135 fn trim(
136 srs: impl Borrow<Self::SRS>,
137 supported_degree: usize,
138 supported_num_vars: Option<usize>,
139 ) -> Result<
140 (
141 <Self::SRS as StructuredReferenceString>::ProverParam,
142 <Self::SRS as StructuredReferenceString>::VerifierParam,
143 ),
144 PCSError,
145 >;
146
147 fn commit(
149 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
150 poly: &Self::Polynomial,
151 ) -> Result<Self::Commitment, PCSError>;
152
153 fn batch_commit(
155 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
156 polys: &[Self::Polynomial],
157 ) -> Result<Self::BatchCommitment, PCSError>;
158
159 fn open(
162 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
163 polynomial: &Self::Polynomial,
164 point: &Self::Point,
165 ) -> Result<(Self::Proof, Self::Evaluation), PCSError>;
166
167 fn batch_open(
170 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
171 batch_commitment: &Self::BatchCommitment,
172 polynomials: &[Self::Polynomial],
173 points: &[Self::Point],
174 ) -> Result<(Self::BatchProof, Vec<Self::Evaluation>), PCSError>;
175
176 #[allow(clippy::type_complexity)]
179 fn multi_open(
180 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
181 polynomial: &Self::Polynomial,
182 points: &[Self::Point],
183 ) -> Result<(Vec<Self::Proof>, Vec<Self::Evaluation>), PCSError> {
184 Ok(points
185 .iter()
186 .map(|point| Self::open(prover_param.borrow(), polynomial, point))
187 .collect::<Result<Vec<_>, _>>()
188 .map_err(PCSError::from)?
189 .into_iter()
190 .unzip())
191 }
192
193 fn verify(
196 verifier_param: &<Self::SRS as StructuredReferenceString>::VerifierParam,
197 commitment: &Self::Commitment,
198 point: &Self::Point,
199 value: &Self::Evaluation,
200 proof: &Self::Proof,
201 ) -> Result<bool, PCSError>;
202
203 fn batch_verify<R: RngCore + CryptoRng>(
206 verifier_param: &<Self::SRS as StructuredReferenceString>::VerifierParam,
207 multi_commitment: &Self::BatchCommitment,
208 points: &[Self::Point],
209 values: &[Self::Evaluation],
210 batch_proof: &Self::BatchProof,
211 rng: &mut R,
212 ) -> Result<bool, PCSError>;
213}
214
215pub trait StructuredReferenceString: Sized {
217 type ProverParam;
219 type VerifierParam;
221
222 fn extract_prover_param(&self, supported_degree: usize) -> Self::ProverParam;
224 fn extract_verifier_param(&self, supported_degree: usize) -> Self::VerifierParam;
226
227 fn trim(
237 &self,
238 supported_degree: usize,
239 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError>;
240
241 fn trim_with_verifier_degree(
252 &self,
253 prover_supported_degree: usize,
254 verifier_supported_degree: usize,
255 ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError>;
256
257 #[cfg(any(test, feature = "test-srs"))]
266 fn gen_srs_for_testing<R: RngCore + CryptoRng>(
267 rng: &mut R,
268 supported_degree: usize,
269 ) -> Result<Self, PCSError>;
270
271 #[cfg(any(test, feature = "test-srs"))]
281 fn gen_srs_for_testing_with_verifier_degree<R: RngCore + CryptoRng>(
282 rng: &mut R,
283 prover_supported_degree: usize,
284 verifier_supported_degree: usize,
285 ) -> Result<Self, PCSError>;
286
287 fn load_srs_from_file(_supported_degree: usize, _file: Option<&str>) -> Result<Self, PCSError> {
294 unimplemented!("TODO: implement loading SRS from files");
295 }
296}
297
298pub trait UnivariatePCS: PolynomialCommitmentScheme
300where
301 Self::Evaluation: FftField,
302{
303 #[allow(clippy::type_complexity)]
307 fn trim_fft_size(
308 srs: impl Borrow<Self::SRS>,
309 supported_degree: usize,
310 ) -> Result<
311 (
312 <Self::SRS as StructuredReferenceString>::ProverParam,
313 <Self::SRS as StructuredReferenceString>::VerifierParam,
314 ),
315 PCSError,
316 > {
317 let fft_degree = checked_fft_size(supported_degree)?;
318 srs.borrow().trim(fft_degree).map_err(|e| {
319 PCSError::InvalidParameters(ark_std::format!(
320 "Requesting degree of {} for FFT:\n\t\t{:?}",
321 fft_degree,
322 e
323 ))
324 })
325 }
326
327 fn multi_open_rou_eval_domain(
331 degree: usize,
332 num_points: usize,
333 ) -> Result<Radix2EvaluationDomain<Self::Evaluation>, PCSError> {
334 let padded_degree = checked_fft_size(degree)?;
336
337 let domain_size = cmp::max(padded_degree + 1, num_points);
338 let domain = Radix2EvaluationDomain::new(domain_size).ok_or_else(|| {
339 PCSError::UpstreamError(ark_std::format!(
340 "Fail to init eval domain of size {}",
341 domain_size
342 ))
343 })?;
344
345 Ok(domain)
346 }
347
348 #[allow(clippy::type_complexity)]
352 fn multi_open_rou(
353 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
354 polynomial: &Self::Polynomial,
355 num_points: usize,
356 domain: &Radix2EvaluationDomain<Self::Evaluation>,
357 ) -> Result<(Vec<Self::Proof>, Vec<Self::Evaluation>), PCSError> {
358 let evals = Self::multi_open_rou_evals(polynomial, num_points, domain)?;
359 let proofs = Self::multi_open_rou_proofs(prover_param, polynomial, num_points, domain)?;
360 Ok((proofs, evals))
361 }
362
363 fn multi_open_rou_proofs(
365 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
366 polynomial: &Self::Polynomial,
367 num_points: usize,
368 domain: &Radix2EvaluationDomain<Self::Evaluation>,
369 ) -> Result<Vec<Self::Proof>, PCSError>;
370
371 fn multi_open_rou_evals(
373 polynomial: &Self::Polynomial,
374 num_points: usize,
375 domain: &Radix2EvaluationDomain<Self::Evaluation>,
376 ) -> Result<Vec<Self::Evaluation>, PCSError>;
377
378 fn multi_point_open(
382 prover_param: impl Borrow<<Self::SRS as StructuredReferenceString>::ProverParam>,
383 polynomial: &Self::Polynomial,
384 points: &[Self::Point],
385 ) -> Result<(Self::Proof, Vec<Self::Evaluation>), PCSError>;
386
387 fn multi_point_verify(
390 verifier_param: impl Borrow<<Self::SRS as StructuredReferenceString>::VerifierParam>,
391 commitment: &Self::Commitment,
392 points: &[Self::Point],
393 values: &[Self::Evaluation],
394 proof: &Self::Proof,
395 ) -> Result<bool, PCSError>;
396}
397
398#[inline]
400pub fn checked_fft_size(degree: usize) -> Result<usize, PCSError> {
401 let err = || {
402 PCSError::InvalidParameters(ark_std::format!(
403 "Next power of two overflows! Got: {}",
404 degree
405 ))
406 };
407 if degree.is_power_of_two() {
408 degree.checked_mul(2).ok_or_else(err)
409 } else {
410 degree.checked_next_power_of_two().ok_or_else(err)
411 }
412}
413
414#[cfg(feature = "icicle")]
416pub mod icicle_deps {
417 use anyhow::anyhow;
418 pub use icicle_core::{
419 curve::{Affine as IcicleAffine, Curve as IcicleCurve, Projective as IcicleProjective},
420 msm::{MSMConfig, MSM},
421 };
422 pub use icicle_cuda_runtime::{memory::HostOrDeviceSlice, stream::CudaStream};
423
424 pub mod curves {
427 pub use ark_bn254::Bn254;
428 pub use icicle_bn254::curve::CurveCfg as IcicleBn254;
429 }
430
431 pub use crate::univariate_kzg::icicle::GPUCommittable;
432
433 pub fn warmup_new_stream() -> anyhow::Result<CudaStream> {
437 let stream = CudaStream::create().map_err(|e| anyhow!("{:?}", e))?;
438 let _warmup_bytes = HostOrDeviceSlice::<'_, u8>::cuda_malloc_async(1024, &stream)
439 .map_err(|e| anyhow!("{:?}", e))?;
440 Ok(stream)
441 }
442}