1use crate::Polynomial;
2use ark_ff::{Field, PrimeField, ToConstraintField};
3use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
4use ark_std::{
5 borrow::Borrow,
6 marker::PhantomData,
7 ops::{AddAssign, MulAssign, SubAssign},
8 rand::RngCore,
9};
10#[cfg(not(feature = "std"))]
11use ark_std::{string::String, vec::Vec};
12
13pub type PolynomialLabel = String;
15
16pub trait PCUniversalParams:
19 Clone + core::fmt::Debug + CanonicalSerialize + CanonicalDeserialize
20{
21 fn max_degree(&self) -> usize;
23}
24
25pub trait PCCommitterKey:
28 Clone + core::fmt::Debug + CanonicalSerialize + CanonicalDeserialize
29{
30 fn max_degree(&self) -> usize;
33
34 fn supported_degree(&self) -> usize;
36}
37
38pub trait PCVerifierKey:
41 Clone + core::fmt::Debug + CanonicalSerialize + CanonicalDeserialize
42{
43 fn max_degree(&self) -> usize;
46
47 fn supported_degree(&self) -> usize;
49}
50
51pub trait PCPreparedVerifierKey<Unprepared: PCVerifierKey> {
54 fn prepare(vk: &Unprepared) -> Self;
56}
57
58pub trait PCCommitment: Clone + CanonicalSerialize + CanonicalDeserialize {
61 fn empty() -> Self;
63
64 fn has_degree_bound(&self) -> bool;
66}
67
68pub trait PCPreparedCommitment<UNPREPARED: PCCommitment>: Clone {
71 fn prepare(comm: &UNPREPARED) -> Self;
73}
74
75pub trait PCCommitmentState: Clone + CanonicalSerialize + CanonicalDeserialize {
78 type Randomness: Clone + CanonicalSerialize + CanonicalDeserialize;
80
81 fn empty() -> Self;
83
84 fn rand<R: RngCore>(
90 num_queries: usize,
91 has_degree_bound: bool,
92 num_vars: Option<usize>,
93 rng: &mut R,
94 ) -> Self::Randomness;
95}
96#[derive(Clone, CanonicalSerialize, CanonicalDeserialize)]
98pub struct BatchLCProof<F: PrimeField, T: Clone + CanonicalSerialize + CanonicalDeserialize> {
99 pub proof: T,
101 pub evals: Option<Vec<F>>,
103}
104
105#[derive(Debug, Clone, CanonicalSerialize, CanonicalDeserialize)]
109pub struct LabeledPolynomial<F: Field, P: Polynomial<F>> {
110 label: PolynomialLabel,
111 polynomial: P,
112 degree_bound: Option<usize>,
113 hiding_bound: Option<usize>,
114 _field: PhantomData<F>,
115}
116
117impl<'a, F: Field, P: Polynomial<F>> core::ops::Deref for LabeledPolynomial<F, P> {
118 type Target = P;
119
120 fn deref(&self) -> &Self::Target {
121 &self.polynomial
122 }
123}
124
125impl<'a, F: Field, P: Polynomial<F>> LabeledPolynomial<F, P> {
126 pub fn new(
128 label: PolynomialLabel,
129 polynomial: P,
130 degree_bound: Option<usize>,
131 hiding_bound: Option<usize>,
132 ) -> Self {
133 Self {
134 label,
135 polynomial: polynomial,
136 degree_bound,
137 hiding_bound,
138 _field: PhantomData,
139 }
140 }
141
142 pub fn label(&self) -> &String {
144 &self.label
145 }
146
147 pub fn polynomial(&self) -> &P {
149 &self.polynomial
150 }
151 pub fn polynomial_mut(&mut self) -> &mut P {
153 &mut self.polynomial
154 }
155
156 pub fn evaluate(&self, point: &P::Point) -> F {
158 self.polynomial.evaluate(point)
159 }
160
161 pub fn degree(&self) -> usize {
163 self.polynomial.degree()
164 }
165
166 pub fn degree_bound(&self) -> Option<usize> {
168 self.degree_bound
169 }
170
171 pub fn is_hiding(&self) -> bool {
173 self.hiding_bound.is_some()
174 }
175
176 pub fn hiding_bound(&self) -> Option<usize> {
178 self.hiding_bound
179 }
180}
181
182#[derive(Clone)]
184pub struct LabeledCommitment<C: PCCommitment> {
185 label: PolynomialLabel,
186 commitment: C,
187 degree_bound: Option<usize>,
188}
189
190impl<F: Field, C: PCCommitment + ToConstraintField<F>> ToConstraintField<F>
191 for LabeledCommitment<C>
192{
193 fn to_field_elements(&self) -> Option<Vec<F>> {
194 self.commitment.to_field_elements()
195 }
196}
197
198impl<C: PCCommitment> LabeledCommitment<C> {
199 pub fn new(label: PolynomialLabel, commitment: C, degree_bound: Option<usize>) -> Self {
201 Self {
202 label,
203 commitment,
204 degree_bound,
205 }
206 }
207
208 pub fn label(&self) -> &String {
210 &self.label
211 }
212
213 pub fn commitment(&self) -> &C {
215 &self.commitment
216 }
217
218 pub fn degree_bound(&self) -> Option<usize> {
220 self.degree_bound
221 }
222}
223
224#[derive(Hash, Ord, PartialOrd, Clone, Eq, PartialEq, Debug)]
226pub enum LCTerm {
227 One,
229 PolyLabel(String),
231}
232
233impl LCTerm {
234 #[inline]
236 pub fn is_one(&self) -> bool {
237 if let LCTerm::One = self {
238 true
239 } else {
240 false
241 }
242 }
243}
244
245impl From<PolynomialLabel> for LCTerm {
246 fn from(other: PolynomialLabel) -> Self {
247 Self::PolyLabel(other)
248 }
249}
250
251impl<'a> From<&'a str> for LCTerm {
252 fn from(other: &str) -> Self {
253 Self::PolyLabel(other.into())
254 }
255}
256
257impl core::convert::TryInto<PolynomialLabel> for LCTerm {
258 type Error = ();
259 fn try_into(self) -> Result<PolynomialLabel, ()> {
260 match self {
261 Self::One => Err(()),
262 Self::PolyLabel(l) => Ok(l),
263 }
264 }
265}
266
267impl<'a> core::convert::TryInto<&'a PolynomialLabel> for &'a LCTerm {
268 type Error = ();
269
270 fn try_into(self) -> Result<&'a PolynomialLabel, ()> {
271 match self {
272 LCTerm::One => Err(()),
273 LCTerm::PolyLabel(l) => Ok(l),
274 }
275 }
276}
277
278impl<B: Borrow<String>> PartialEq<B> for LCTerm {
279 fn eq(&self, other: &B) -> bool {
280 match self {
281 Self::One => false,
282 Self::PolyLabel(l) => l == other.borrow(),
283 }
284 }
285}
286
287#[derive(Clone, Debug)]
289pub struct LinearCombination<F> {
290 pub label: String,
292 pub terms: Vec<(F, LCTerm)>,
294}
295
296impl<F: Field> LinearCombination<F> {
297 pub fn empty(label: impl Into<String>) -> Self {
299 Self {
300 label: label.into(),
301 terms: Vec::new(),
302 }
303 }
304
305 pub fn new(label: impl Into<String>, terms: Vec<(F, impl Into<LCTerm>)>) -> Self {
308 let terms = terms.into_iter().map(|(c, t)| (c, t.into())).collect();
309 Self {
310 label: label.into(),
311 terms: terms,
312 }
313 }
314
315 pub fn label(&self) -> &String {
317 &self.label
318 }
319
320 pub fn is_empty(&self) -> bool {
322 self.terms.is_empty()
323 }
324
325 pub fn push(&mut self, term: (F, LCTerm)) -> &mut Self {
327 self.terms.push(term);
328 self
329 }
330}
331
332impl<'a, F: Field> AddAssign<(F, &'a LinearCombination<F>)> for LinearCombination<F> {
333 fn add_assign(&mut self, (coeff, other): (F, &'a LinearCombination<F>)) {
334 self.terms
335 .extend(other.terms.iter().map(|(c, t)| (coeff * c, t.clone())));
336 }
337}
338
339impl<'a, F: Field> SubAssign<(F, &'a LinearCombination<F>)> for LinearCombination<F> {
340 fn sub_assign(&mut self, (coeff, other): (F, &'a LinearCombination<F>)) {
341 self.terms
342 .extend(other.terms.iter().map(|(c, t)| (-coeff * c, t.clone())));
343 }
344}
345
346impl<'a, F: Field> AddAssign<&'a LinearCombination<F>> for LinearCombination<F> {
347 fn add_assign(&mut self, other: &'a LinearCombination<F>) {
348 self.terms.extend(other.terms.iter().cloned());
349 }
350}
351
352impl<'a, F: Field> SubAssign<&'a LinearCombination<F>> for LinearCombination<F> {
353 fn sub_assign(&mut self, other: &'a LinearCombination<F>) {
354 self.terms
355 .extend(other.terms.iter().map(|(c, t)| (-*c, t.clone())));
356 }
357}
358
359impl<F: Field> AddAssign<F> for LinearCombination<F> {
360 fn add_assign(&mut self, coeff: F) {
361 self.terms.push((coeff, LCTerm::One));
362 }
363}
364
365impl<F: Field> SubAssign<F> for LinearCombination<F> {
366 fn sub_assign(&mut self, coeff: F) {
367 self.terms.push((-coeff, LCTerm::One));
368 }
369}
370
371impl<F: Field> MulAssign<F> for LinearCombination<F> {
372 fn mul_assign(&mut self, coeff: F) {
373 self.terms.iter_mut().for_each(|(c, _)| *c *= coeff);
374 }
375}
376
377impl<F: Field> core::ops::Deref for LinearCombination<F> {
378 type Target = [(F, LCTerm)];
379
380 fn deref(&self) -> &Self::Target {
381 &self.terms
382 }
383}