1use std::borrow::Borrow;
20use std::cmp::Ordering;
21use std::fmt::{self, Debug, Formatter};
22use std::hash::{Hash, Hasher};
23use std::iter::repeat_with;
24use std::ops::{AddAssign, Mul, MulAssign, SubAssign};
25use std::{cmp, iter, ops};
26
27use group::{prime::PrimeCurveAffine, Curve, Group};
28use rand::Rng;
29use serde::{Deserialize, Serialize};
30use zeroize::Zeroize;
31
32use crate::cmp_pairing::cmp_affine;
33use crate::convert::{fr_from_bytes, g1_from_bytes};
34use crate::error::{Error, Result};
35use crate::into_fr::IntoFr;
36use crate::secret::clear_fr;
37use crate::{Field, Fr, G1Affine, G1Projective, PK_SIZE, SK_SIZE};
38
39#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
41pub struct Poly {
42 #[serde(with = "super::serde_impl::field_vec")]
44 pub(super) coeff: Vec<Fr>,
45}
46
47impl Zeroize for Poly {
48 fn zeroize(&mut self) {
49 for fr in self.coeff.iter_mut() {
50 clear_fr(fr)
51 }
52 }
53}
54
55impl Drop for Poly {
56 fn drop(&mut self) {
57 self.zeroize();
58 }
59}
60
61impl Debug for Poly {
63 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64 f.debug_struct("Poly").field("coeff", &"...").finish()
65 }
66}
67
68#[allow(clippy::suspicious_op_assign_impl)]
69impl<B: Borrow<Poly>> ops::AddAssign<B> for Poly {
70 fn add_assign(&mut self, rhs: B) {
71 let len = self.coeff.len();
72 let rhs_len = rhs.borrow().coeff.len();
73 if rhs_len > len {
74 self.coeff.resize(rhs_len, Fr::zero());
75 }
76 for (self_c, rhs_c) in self.coeff.iter_mut().zip(&rhs.borrow().coeff) {
77 self_c.add_assign(rhs_c);
78 }
79 self.remove_zeros();
80 }
81}
82
83impl<'a, B: Borrow<Poly>> ops::Add<B> for &'a Poly {
84 type Output = Poly;
85
86 fn add(self, rhs: B) -> Poly {
87 (*self).clone() + rhs
88 }
89}
90
91impl<B: Borrow<Poly>> ops::Add<B> for Poly {
92 type Output = Poly;
93
94 fn add(mut self, rhs: B) -> Poly {
95 self += rhs;
96 self
97 }
98}
99
100impl ops::Add<Fr> for Poly {
101 type Output = Poly;
102
103 fn add(mut self, rhs: Fr) -> Self::Output {
104 if self.is_zero() && !bool::from(rhs.is_zero()) {
105 self.coeff.push(rhs);
106 } else {
107 self.coeff[0].add_assign(&rhs);
108 self.remove_zeros();
109 }
110 self
111 }
112}
113
114impl ops::Add<u64> for Poly {
115 type Output = Poly;
116
117 fn add(self, rhs: u64) -> Self::Output {
118 self + Fr::from(rhs)
119 }
120}
121
122impl<B: Borrow<Poly>> ops::SubAssign<B> for Poly {
123 fn sub_assign(&mut self, rhs: B) {
124 let len = self.coeff.len();
125 let rhs_len = rhs.borrow().coeff.len();
126 if rhs_len > len {
127 self.coeff.resize(rhs_len, Fr::zero());
128 }
129 for (self_c, rhs_c) in self.coeff.iter_mut().zip(&rhs.borrow().coeff) {
130 self_c.sub_assign(rhs_c);
131 }
132 self.remove_zeros();
133 }
134}
135
136impl<'a, B: Borrow<Poly>> ops::Sub<B> for &'a Poly {
137 type Output = Poly;
138
139 fn sub(self, rhs: B) -> Poly {
140 (*self).clone() - rhs
141 }
142}
143
144impl<B: Borrow<Poly>> ops::Sub<B> for Poly {
145 type Output = Poly;
146
147 fn sub(mut self, rhs: B) -> Poly {
148 self -= rhs;
149 self
150 }
151}
152
153impl ops::Sub<Fr> for Poly {
154 type Output = Poly;
155
156 fn sub(self, mut rhs: Fr) -> Self::Output {
157 rhs = -rhs;
158 self + rhs
159 }
160}
161
162impl ops::Sub<u64> for Poly {
163 type Output = Poly;
164
165 fn sub(self, rhs: u64) -> Self::Output {
166 self - Fr::from(rhs)
167 }
168}
169
170#[allow(clippy::suspicious_arithmetic_impl)]
172impl<'a, B: Borrow<Poly>> ops::Mul<B> for &'a Poly {
173 type Output = Poly;
174
175 fn mul(self, rhs: B) -> Self::Output {
176 let rhs = rhs.borrow();
177 if rhs.is_zero() || self.is_zero() {
178 return Poly::zero();
179 }
180 let n_coeffs = self.coeff.len() + rhs.coeff.len() - 1;
181 let mut coeffs = vec![Fr::zero(); n_coeffs];
182 let mut tmp = Fr::zero();
183 for (i, ca) in self.coeff.iter().enumerate() {
184 for (j, cb) in rhs.coeff.iter().enumerate() {
185 tmp = *ca;
186 tmp.mul_assign(cb);
187 coeffs[i + j].add_assign(&tmp);
188 }
189 }
190 clear_fr(&mut tmp);
191 Poly::from(coeffs)
192 }
193}
194
195impl<B: Borrow<Poly>> ops::Mul<B> for Poly {
196 type Output = Poly;
197
198 fn mul(self, rhs: B) -> Self::Output {
199 &self * rhs
200 }
201}
202
203impl<B: Borrow<Self>> ops::MulAssign<B> for Poly {
204 fn mul_assign(&mut self, rhs: B) {
205 *self = &*self * rhs;
206 }
207}
208
209impl ops::MulAssign<Fr> for Poly {
210 fn mul_assign(&mut self, rhs: Fr) {
211 if bool::from(rhs.is_zero()) {
212 self.zeroize();
213 self.coeff.clear();
214 } else {
215 for c in &mut self.coeff {
216 c.mul_assign(&rhs);
217 }
218 }
219 }
220}
221
222impl<'a> ops::Mul<&'a Fr> for Poly {
223 type Output = Poly;
224
225 fn mul(mut self, rhs: &Fr) -> Self::Output {
226 if bool::from(rhs.is_zero()) {
227 self.zeroize();
228 self.coeff.clear();
229 } else {
230 self.coeff.iter_mut().for_each(|c| c.mul_assign(rhs));
231 }
232 self
233 }
234}
235
236impl ops::Mul<Fr> for Poly {
237 type Output = Poly;
238
239 fn mul(self, rhs: Fr) -> Self::Output {
240 let rhs = &rhs;
241 self * rhs
242 }
243}
244
245impl<'a> ops::Mul<&'a Fr> for &'a Poly {
246 type Output = Poly;
247
248 fn mul(self, rhs: &Fr) -> Self::Output {
249 (*self).clone() * rhs
250 }
251}
252
253impl<'a> ops::Mul<Fr> for &'a Poly {
254 type Output = Poly;
255
256 fn mul(self, rhs: Fr) -> Self::Output {
257 (*self).clone() * rhs
258 }
259}
260
261impl ops::Mul<u64> for Poly {
262 type Output = Poly;
263
264 fn mul(self, rhs: u64) -> Self::Output {
265 self * Fr::from(rhs)
266 }
267}
268
269impl From<Vec<Fr>> for Poly {
272 fn from(coeff: Vec<Fr>) -> Self {
273 Poly { coeff }
274 }
275}
276
277impl Poly {
278 pub fn random<R: Rng>(degree: usize, rng: &mut R) -> Self {
284 Poly::try_random(degree, rng)
285 .unwrap_or_else(|e| panic!("Failed to create random `Poly`: {e}"))
286 }
287
288 pub fn try_random<R: Rng>(degree: usize, rng: &mut R) -> Result<Self> {
292 if degree == usize::max_value() {
293 return Err(Error::DegreeTooHigh);
294 }
295 let coeff: Vec<Fr> = repeat_with(|| Fr::random(&mut *rng))
296 .take(degree + 1)
297 .collect();
298 Ok(Poly::from(coeff))
299 }
300
301 pub fn zero() -> Self {
303 Poly { coeff: vec![] }
304 }
305
306 pub fn is_zero(&self) -> bool {
308 self.coeff.iter().all(|coeff| bool::from(coeff.is_zero()))
309 }
310
311 pub fn one() -> Self {
313 Poly::constant(Fr::one())
314 }
315
316 pub fn constant(mut c: Fr) -> Self {
318 let poly = Poly::from(vec![c]);
322 clear_fr(&mut c);
323 poly
324 }
325
326 pub fn identity() -> Self {
328 Poly::monomial(1)
329 }
330
331 pub fn monomial(degree: usize) -> Self {
333 let coeff: Vec<Fr> = iter::repeat(Fr::zero())
334 .take(degree)
335 .chain(iter::once(Fr::one()))
336 .collect();
337 Poly::from(coeff)
338 }
339
340 pub fn interpolate<T, U, I>(samples_repr: I) -> Result<Self>
343 where
344 I: IntoIterator<Item = (T, U)>,
345 T: IntoFr,
346 U: IntoFr,
347 {
348 let convert = |(x, y): (T, U)| (x.into_fr(), y.into_fr());
349 let samples: Vec<(Fr, Fr)> = samples_repr.into_iter().map(convert).collect();
350 Poly::compute_interpolation(&samples)
351 }
352
353 pub fn degree(&self) -> usize {
355 self.coeff.len().saturating_sub(1)
356 }
357
358 pub fn evaluate<T: IntoFr>(&self, i: T) -> Fr {
360 let mut result = match self.coeff.last() {
361 None => return Fr::zero(),
362 Some(c) => *c,
363 };
364 let x = i.into_fr();
365 for c in self.coeff.iter().rev().skip(1) {
366 result.mul_assign(&x);
367 result.add_assign(c);
368 }
369 result
370 }
371
372 pub fn commitment(&self) -> Commitment {
374 let to_g1 = |c: &Fr| G1Affine::generator().mul(c).to_affine();
375 Commitment {
376 coeff: self.coeff.iter().map(to_g1).collect(),
377 }
378 }
379
380 pub fn to_bytes(&self) -> Vec<u8> {
382 let coeff_size = self.coeff.len();
383 let bytes_size = coeff_size * SK_SIZE;
384 let mut poly_bytes = vec![0; bytes_size];
385 for i in 0..coeff_size {
386 let fr = self.coeff[i];
387 let fr_bytes = fr.to_bytes_be();
388 let fr_size = fr_bytes.len();
389 for j in 0..fr_size {
390 poly_bytes[i * SK_SIZE + j] = fr_bytes[j];
391 }
392 }
393 poly_bytes
394 }
395
396 pub fn from_bytes(bytes: Vec<u8>) -> Result<Self> {
398 let mut c: Vec<Fr> = vec![];
399 let coeff_size = bytes.len() / SK_SIZE;
400 for i in 0..coeff_size {
401 let mut fr_bytes = [0u8; SK_SIZE];
402 for j in 0..SK_SIZE {
403 fr_bytes[j] = bytes[i * SK_SIZE + j];
404 }
405 let fr = fr_from_bytes(fr_bytes)?;
406 c.push(fr);
407 }
408 Ok(Poly { coeff: c })
409 }
410
411 fn remove_zeros(&mut self) {
413 let zeros = self
414 .coeff
415 .iter()
416 .rev()
417 .take_while(|c| bool::from(c.is_zero()))
418 .count();
419 let len = self.coeff.len() - zeros;
420 self.coeff.truncate(len);
421 }
422
423 fn compute_interpolation(samples: &[(Fr, Fr)]) -> Result<Self> {
426 if samples.is_empty() {
427 return Ok(Poly::zero());
428 }
429 let mut poly = Poly::constant(samples[0].1);
431 let mut minus_s0 = samples[0].0;
432 minus_s0 = -minus_s0;
433 let mut base = Poly::from(vec![minus_s0, Fr::one()]);
435
436 for (ref x, ref y) in &samples[1..] {
439 let mut diff = *y;
442 diff.sub_assign(&poly.evaluate(x));
443 let base_val = base.evaluate(x);
444 let base_val_inv = &base_val.invert();
447 if base_val_inv.is_none().into() {
448 return Err(Error::DuplicateEntry);
449 }
450 diff.mul_assign(&base_val_inv.unwrap());
451 base *= diff;
452 poly += &base;
453
454 base *= Poly::from(vec![-x, Fr::one()]);
456 }
457 Ok(poly)
458 }
459
460 pub fn reveal(&self) -> String {
464 format!("Poly {{ coeff: {:?} }}", self.coeff)
465 }
466}
467
468#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
470pub struct Commitment {
471 #[serde(with = "super::serde_impl::affine_vec")]
473 pub(super) coeff: Vec<G1Affine>,
474}
475
476impl From<Vec<G1Affine>> for Commitment {
478 fn from(coeff: Vec<G1Affine>) -> Self {
479 Commitment { coeff }
480 }
481}
482
483impl PartialOrd for Commitment {
484 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
485 Some(self.cmp(other))
486 }
487}
488
489impl Ord for Commitment {
490 fn cmp(&self, other: &Self) -> Ordering {
491 self.coeff.len().cmp(&other.coeff.len()).then_with(|| {
492 self.coeff
493 .iter()
494 .zip(&other.coeff)
495 .find(|(x, y)| x != y)
496 .map_or(Ordering::Equal, |(x, y)| cmp_affine(x, y))
497 })
498 }
499}
500
501impl Hash for Commitment {
502 fn hash<H: Hasher>(&self, state: &mut H) {
503 self.coeff.len().hash(state);
504 for c in &self.coeff {
505 c.to_compressed().hash(state);
506 }
507 }
508}
509
510impl<B: Borrow<Commitment>> ops::AddAssign<B> for Commitment {
511 fn add_assign(&mut self, rhs: B) {
512 let len = cmp::max(self.coeff.len(), rhs.borrow().coeff.len());
513 self.coeff.resize(len, G1Affine::identity());
514 for (self_c, rhs_c) in self.coeff.iter_mut().zip(&rhs.borrow().coeff) {
515 *self_c = (*self_c + G1Projective::from(rhs_c)).to_affine();
516 }
517 self.remove_zeros();
518 }
519}
520
521impl<'a, B: Borrow<Commitment>> ops::Add<B> for &'a Commitment {
522 type Output = Commitment;
523
524 fn add(self, rhs: B) -> Commitment {
525 (*self).clone() + rhs
526 }
527}
528
529impl<B: Borrow<Commitment>> ops::Add<B> for Commitment {
530 type Output = Commitment;
531
532 fn add(mut self, rhs: B) -> Commitment {
533 self += rhs;
534 self
535 }
536}
537
538impl Commitment {
539 pub fn degree(&self) -> usize {
541 self.coeff.len() - 1
542 }
543
544 pub fn evaluate<T: IntoFr>(&self, i: T) -> G1Affine {
546 let mut result = match self.coeff.last() {
547 None => return G1Affine::identity(),
548 Some(c) => G1Projective::from(c),
549 };
550 let x = i.into_fr();
551 for c in self.coeff.iter().rev().skip(1) {
552 result.mul_assign(x);
553 result.add_assign(c);
554 }
555 result.to_affine()
556 }
557
558 pub fn to_bytes(&self) -> Vec<u8> {
560 let coeff_size = self.coeff.len();
561 let bytes_size = coeff_size * PK_SIZE;
562 let mut commit_bytes = vec![0; bytes_size];
563 for i in 0..coeff_size {
564 let g1 = self.coeff[i];
565 let g1_bytes = g1.to_compressed();
566 let g1_size = g1_bytes.len();
567 for j in 0..g1_size {
568 commit_bytes[i * PK_SIZE + j] = g1_bytes[j];
569 }
570 }
571 commit_bytes
572 }
573
574 pub fn from_bytes(bytes: Vec<u8>) -> Result<Self> {
576 let mut c: Vec<G1Affine> = vec![];
577 let coeff_size = bytes.len() / PK_SIZE;
578 for i in 0..coeff_size {
579 let mut g1_bytes = [0; PK_SIZE];
580 for j in 0..PK_SIZE {
581 g1_bytes[j] = bytes[i * PK_SIZE + j];
582 }
583 let g1 = g1_from_bytes(g1_bytes)?;
584 c.push(g1);
585 }
586 Ok(Commitment { coeff: c })
587 }
588
589 fn remove_zeros(&mut self) {
591 let zeros = self
592 .coeff
593 .iter()
594 .rev()
595 .take_while(|c| bool::from(c.is_identity()))
596 .count();
597 let len = self.coeff.len() - zeros;
598 self.coeff.truncate(len)
599 }
600}
601
602#[derive(Clone)]
607pub struct BivarPoly {
608 degree: usize,
610 coeff: Vec<Fr>,
613}
614
615impl Zeroize for BivarPoly {
616 fn zeroize(&mut self) {
617 for fr in self.coeff.iter_mut() {
618 clear_fr(fr)
619 }
620 self.degree.zeroize();
621 }
622}
623
624impl Drop for BivarPoly {
625 fn drop(&mut self) {
626 self.zeroize();
627 }
628}
629
630impl Debug for BivarPoly {
632 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
633 f.debug_struct("BivarPoly")
634 .field("degree", &self.degree)
635 .field("coeff", &"...")
636 .finish()
637 }
638}
639
640impl BivarPoly {
641 pub fn random<R: Rng>(degree: usize, rng: &mut R) -> Self {
647 BivarPoly::try_random(degree, rng).unwrap_or_else(|e| {
648 panic!("Failed to create random `BivarPoly` of degree {degree}: {e}")
649 })
650 }
651
652 pub fn try_random<R: Rng>(degree: usize, rng: &mut R) -> Result<Self> {
654 let len = coeff_pos(degree, degree)
655 .and_then(|l| l.checked_add(1))
656 .ok_or(Error::DegreeTooHigh)?;
657 let poly = BivarPoly {
658 degree,
659 coeff: repeat_with(|| Fr::random(&mut *rng)).take(len).collect(),
660 };
661 Ok(poly)
662 }
663
664 pub fn degree(&self) -> usize {
666 self.degree
667 }
668
669 pub fn evaluate<T: IntoFr>(&self, x: T, y: T) -> Fr {
671 let x_pow = self.powers(x);
672 let y_pow = self.powers(y);
673 let mut result = Fr::zero();
675 for (i, x_pow_i) in x_pow.into_iter().enumerate() {
676 for (j, y_pow_j) in y_pow.iter().enumerate() {
677 let index = coeff_pos(i, j).expect("polynomial degree too high");
678 let mut summand = self.coeff[index];
679 summand.mul_assign(&x_pow_i);
680 summand.mul_assign(y_pow_j);
681 result.add_assign(&summand);
682 }
683 }
684 result
685 }
686
687 pub fn row<T: IntoFr>(&self, x: T) -> Poly {
689 let x_pow = self.powers(x);
690 let coeff: Vec<Fr> = (0..=self.degree)
691 .map(|i| {
692 let mut result = Fr::zero();
694 for (j, x_pow_j) in x_pow.iter().enumerate() {
695 let index = coeff_pos(i, j).expect("polynomial degree too high");
696 let mut summand = self.coeff[index];
697 summand.mul_assign(x_pow_j);
698 result.add_assign(&summand);
699 }
700 result
701 })
702 .collect();
703 Poly::from(coeff)
704 }
705
706 pub fn commitment(&self) -> BivarCommitment {
708 let to_pub = |c: &Fr| G1Affine::generator().mul(c).to_affine();
709 BivarCommitment {
710 degree: self.degree,
711 coeff: self.coeff.iter().map(to_pub).collect(),
712 }
713 }
714
715 fn powers<T: IntoFr>(&self, x: T) -> Vec<Fr> {
717 powers(x, self.degree)
718 }
719
720 pub fn reveal(&self) -> String {
724 format!(
725 "BivarPoly {{ degree: {}, coeff: {:?} }}",
726 self.degree, self.coeff
727 )
728 }
729
730 pub fn to_bytes(&self) -> Vec<u8> {
732 let coeff_size = self.coeff.len();
733 let bytes_size = coeff_size * SK_SIZE;
734 let mut poly_bytes = vec![0; bytes_size];
735 for i in 0..coeff_size {
736 let fr = self.coeff[i];
737 let fr_bytes = fr.to_bytes_be();
738 let fr_size = fr_bytes.len();
739 for j in 0..fr_size {
740 poly_bytes[i * SK_SIZE + j] = fr_bytes[j];
741 }
742 }
743 poly_bytes
744 }
745
746 pub fn from_bytes(bytes: Vec<u8>) -> Result<Self> {
748 let mut c: Vec<Fr> = vec![];
749 let coeff_size = bytes.len() / SK_SIZE;
750 for coeff_index in 0..coeff_size {
751 let mut fr_bytes = [0u8; SK_SIZE];
753 for i in 0..SK_SIZE {
754 fr_bytes[i] = bytes[coeff_index * SK_SIZE + i];
755 }
756 let fr = fr_from_bytes(fr_bytes)?;
757 c.push(fr);
758 }
759 let d = ((2 * coeff_size) as f64).sqrt() as usize - 1;
760 Ok(BivarPoly {
761 degree: d,
762 coeff: c,
763 })
764 }
765}
766
767#[derive(Debug, Clone, Eq, PartialEq)]
769pub struct BivarCommitment {
770 pub(crate) degree: usize,
772 pub(crate) coeff: Vec<G1Affine>,
774}
775
776impl Hash for BivarCommitment {
777 fn hash<H: Hasher>(&self, state: &mut H) {
778 self.degree.hash(state);
779 for c in &self.coeff {
780 c.to_compressed().hash(state);
781 }
782 }
783}
784
785impl PartialOrd for BivarCommitment {
786 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
787 Some(self.cmp(other))
788 }
789}
790
791impl Ord for BivarCommitment {
792 fn cmp(&self, other: &Self) -> Ordering {
793 self.degree.cmp(&other.degree).then_with(|| {
794 self.coeff
795 .iter()
796 .zip(&other.coeff)
797 .find(|(x, y)| x != y)
798 .map_or(Ordering::Equal, |(x, y)| cmp_affine(x, y))
799 })
800 }
801}
802
803impl BivarCommitment {
804 pub fn degree(&self) -> usize {
806 self.degree
807 }
808
809 pub fn evaluate<T: IntoFr>(&self, x: T, y: T) -> G1Affine {
811 let x_pow = self.powers(x);
812 let y_pow = self.powers(y);
813 let mut result = G1Projective::identity();
815 for (i, x_pow_i) in x_pow.into_iter().enumerate() {
816 for (j, y_pow_j) in y_pow.iter().enumerate() {
817 let index = coeff_pos(i, j).expect("polynomial degree too high");
818 let mut summand = self.coeff[index];
819 summand.mul_assign(x_pow_i);
820 summand.mul_assign(*y_pow_j);
821 result.add_assign(&summand);
822 }
823 }
824 result.to_affine()
825 }
826
827 pub fn row<T: IntoFr>(&self, x: T) -> Commitment {
829 let x_pow = self.powers(x);
830 let coeff: Vec<G1Affine> = (0..=self.degree)
831 .map(|i| {
832 let mut result = G1Projective::identity();
833 for (j, x_pow_j) in x_pow.iter().enumerate() {
834 let index = coeff_pos(i, j).expect("polynomial degree too high");
835 let mut summand = self.coeff[index];
836 summand.mul_assign(*x_pow_j);
837 result.add_assign(&summand);
838 }
839 result.to_affine()
840 })
841 .collect();
842 Commitment { coeff }
843 }
844
845 fn powers<T: IntoFr>(&self, x: T) -> Vec<Fr> {
847 powers(x, self.degree)
848 }
849
850 pub fn to_bytes(&self) -> Vec<u8> {
852 let coeff_size = self.coeff.len();
853 let bytes_size = coeff_size * PK_SIZE;
854 let mut commit_bytes = vec![0; bytes_size];
855 for i in 0..coeff_size {
856 let g1 = self.coeff[i];
857 let g1_bytes = g1.to_compressed();
858 let g1_size = g1_bytes.len();
859 assert_eq!(g1_size, PK_SIZE);
861 for j in 0..g1_size {
862 commit_bytes[i * PK_SIZE + j] = g1_bytes[j];
863 }
864 }
865 commit_bytes
866 }
867
868 pub fn from_bytes(bytes: Vec<u8>) -> Result<Self> {
870 let mut c: Vec<G1Affine> = vec![];
871 let coeff_size = bytes.len() / PK_SIZE;
872 for i in 0..coeff_size {
873 let mut g1_bytes = [0; PK_SIZE];
874 for j in 0..PK_SIZE {
875 g1_bytes[j] = bytes[i * PK_SIZE + j];
876 }
877 let g1 = g1_from_bytes(g1_bytes)?;
878 c.push(g1);
879 }
880 let d = ((2 * coeff_size) as f64).sqrt() as usize - 1;
881 Ok(BivarCommitment {
882 degree: d,
883 coeff: c,
884 })
885 }
886}
887
888fn powers<T: IntoFr>(into_x: T, degree: usize) -> Vec<Fr> {
890 let x = into_x.into_fr();
891 let mut x_pow_i = Fr::one();
892 iter::once(x_pow_i)
893 .chain((0..degree).map(|_| {
894 x_pow_i.mul_assign(&x);
895 x_pow_i
896 }))
897 .collect()
898}
899
900pub(crate) fn coeff_pos(i: usize, j: usize) -> Option<usize> {
904 let (j, i) = if j >= i { (j, i) } else { (i, j) };
906 i.checked_add(j.checked_mul(j.checked_add(1)?)? / 2)
907}
908
909#[cfg(test)]
910mod tests {
911
912 use super::*;
913 use eyre::{eyre, Result};
914 use group::{ff::Field, prime::PrimeCurveAffine, Curve};
915 use hex_fmt::HexFmt;
916 use std::collections::BTreeMap;
917 use std::ops::{AddAssign, Mul};
918
919 #[test]
920 fn test_coeff_pos() {
921 let mut i = 0;
922 let mut j = 0;
923 for n in 0..100 {
924 assert_eq!(Some(n), coeff_pos(i, j));
925 if i >= j {
926 j += 1;
927 i = 0;
928 } else {
929 i += 1;
930 }
931 }
932 let too_large = 1 << (0usize.count_zeros() / 2);
933 assert_eq!(None, coeff_pos(0, too_large));
934 }
935
936 #[test]
937 fn poly() -> Result<()> {
938 let x_pow_3 = Poly::monomial(3);
940 let x_pow_1 = Poly::monomial(1);
941 let poly = x_pow_3 * 5 + x_pow_1 - 2;
942
943 let coeff: Vec<_> = [-2, 1, 0, 5].iter().map(IntoFr::into_fr).collect();
944 assert_eq!(Poly { coeff }, poly);
945 let samples = vec![(-1, -8), (2, 40), (3, 136), (5, 628)];
946 for &(x, y) in &samples {
947 assert_eq!(y.into_fr(), poly.evaluate(x));
948 }
949 let interp = Poly::interpolate(samples)?;
950 assert_eq!(interp, poly);
951 Ok(())
952 }
953
954 #[test]
955 fn test_zeroize() {
956 let mut poly = Poly::monomial(3) + Poly::monomial(2) - 1;
957 poly.zeroize();
958 assert!(poly.is_zero());
959 let mut bi_poly = BivarPoly::random(3, &mut rand::thread_rng());
960 let random_commitment = bi_poly.commitment();
961 bi_poly.zeroize();
962 let zero_commitment = bi_poly.commitment();
963 assert_ne!(random_commitment, zero_commitment);
964 let mut rng = rand::thread_rng();
965 let (x, y): (Fr, Fr) = (Fr::random(&mut rng), Fr::random(&mut rng));
966 assert_eq!(zero_commitment.evaluate(x, y), G1Affine::identity());
967 }
968
969 #[test]
970 fn distributed_key_generation() -> Result<()> {
971 let mut rng = rand::thread_rng();
972 let dealer_num = 3;
973 let node_num = 5;
974 let faulty_num = 2;
975
976 let bi_polys: Vec<BivarPoly> = (0..dealer_num)
980 .map(|_| BivarPoly::random(faulty_num, &mut rng))
981 .collect();
982 let pub_bi_commits: Vec<_> = bi_polys.iter().map(BivarPoly::commitment).collect();
983
984 let mut sec_keys = vec![Fr::zero(); node_num];
985
986 for (bi_poly, bi_commit) in bi_polys.iter().zip(&pub_bi_commits) {
990 for m in 1..=node_num {
991 let row_poly = bi_poly.row(m);
993 let row_commit = bi_commit.row(m);
994 assert_eq!(row_poly.commitment(), row_commit);
995 for s in 1..=node_num {
997 let val = row_poly.evaluate(s);
998 let val_g1 = G1Affine::generator().mul(val);
999 assert_eq!(bi_commit.evaluate(m, s), val_g1.to_affine());
1000 assert_eq!(bi_poly.evaluate(m, s), val);
1002 }
1003
1004 let x_pow_2 = Poly::monomial(2);
1006 let five = Poly::constant(5.into_fr());
1007 let wrong_poly = row_poly.clone() + x_pow_2 * five;
1008 assert_ne!(wrong_poly.commitment(), row_commit);
1009
1010 let received: BTreeMap<_, _> = [1, 2, 4]
1018 .iter()
1019 .map(|&i| (i, bi_poly.evaluate(m, i)))
1020 .collect();
1021 let my_row = Poly::interpolate(received)?;
1022 assert_eq!(bi_poly.evaluate(m, 0), my_row.evaluate(0));
1023 assert_eq!(row_poly, my_row);
1024
1025 sec_keys[m - 1].add_assign(&my_row.evaluate(Fr::zero()));
1028 }
1029 }
1030
1031 let mut sec_key_set = Poly::zero();
1037 for bi_poly in &bi_polys {
1038 sec_key_set += bi_poly.row(0);
1039 }
1040 for m in 1..=node_num {
1041 assert_eq!(sec_key_set.evaluate(m), sec_keys[m - 1]);
1042 }
1043
1044 let mut sum_commit = Poly::zero().commitment();
1047 for bi_commit in &pub_bi_commits {
1048 sum_commit += bi_commit.row(0);
1049 }
1050 assert_eq!(sum_commit, sec_key_set.commitment());
1051 Ok(())
1052 }
1053
1054 #[test]
1055 fn test_commitment_to_from_bytes() {
1056 let degree = 3;
1057 let mut rng = rand::thread_rng();
1058 let poly = Poly::random(degree, &mut rng);
1059 let commitment = poly.commitment();
1060 let commitment_bytes = commitment.to_bytes();
1062 assert_eq!(commitment_bytes.len(), (degree + 1) * 48);
1063 let g1 = commitment.evaluate(0);
1065 let g1_bytes = g1.to_compressed().as_ref().to_vec();
1066 let g1_bytes_size = g1_bytes.len();
1067 for i in 0..g1_bytes_size {
1068 assert_eq!(g1_bytes[i], commitment_bytes[i]);
1069 }
1070 let restored_commitment =
1072 Commitment::from_bytes(commitment_bytes).expect("invalid commitment bytes");
1073 assert_eq!(commitment, restored_commitment);
1074 }
1076
1077 #[test]
1078 fn test_bivar_commitment_to_from_bytes() {
1079 let mut rng = rand::thread_rng();
1080 let degree = 3;
1081 let bi_poly = BivarPoly::random(degree, &mut rng);
1082 let bi_commit = bi_poly.commitment();
1083 let commitment = bi_commit.row(0);
1084 let bi_commit_bytes = bi_commit.to_bytes();
1086 let dp1 = degree + 1;
1087 let sum = dp1 * (dp1 + 1) / 2; let expected_size = sum * PK_SIZE;
1089 assert_eq!(bi_commit_bytes.len(), expected_size);
1090 let commitment_bytes = commitment.to_bytes();
1092 for i in 0..PK_SIZE {
1093 assert_eq!(commitment_bytes[i], bi_commit_bytes[i]);
1094 }
1095 let restored_bi_commit =
1097 BivarCommitment::from_bytes(bi_commit_bytes).expect("invalid bivar commitment bytes");
1098 assert_eq!(bi_commit, restored_bi_commit);
1099 for i in 0..10 {
1101 assert_eq!(bi_commit.row(i), restored_bi_commit.row(i));
1102 }
1103 }
1104
1105 #[test]
1106 fn vectors_bivar_commitment_to_from_bytes() -> Result<()> {
1107 let vectors = vec![
1108 vec![
1110 "84339010af2fa47ebb8294681b2b61d6ec4c0d6ce595c0a8c57234d348c7be120520a6b710f061196d3fa30323e1bcb48ad0b4a8180ff4ca8888f6e8bd869c43c5b111c2733bab514d826bed4ec10f5ca4aacc838c69cba6a99c14cc59646e69ad14932a863413cbb57d3a0aad84d7ec62276a63990d686058c24fef6e0cc17f9360ac4f8e20725bdabd591ad25c4cf98f9fe02f53ef5876dc6744f18f3462e9a5d0a83d30e949acb2e48ba8ee50d3674a7c4b7d75372983c2fd3e9e9291b0e697993cefe339b05133e2ebb51ff3c63e711969c6d0704631059db9a990183aca270acd5fb82ea78bab983c39290b8c71afd930a68bd2a35bd6fd5e7bc09877dfe7dbafd8f953172016da9cd9e816a09677df3a4c8c2339e530acda235f5feefd",
1112 "84339010af2fa47ebb8294681b2b61d6ec4c0d6ce595c0a8c57234d348c7be120520a6b710f061196d3fa30323e1bcb48ad0b4a8180ff4ca8888f6e8bd869c43c5b111c2733bab514d826bed4ec10f5ca4aacc838c69cba6a99c14cc59646e698f9fe02f53ef5876dc6744f18f3462e9a5d0a83d30e949acb2e48ba8ee50d3674a7c4b7d75372983c2fd3e9e9291b0e6",
1114 "b9ee0808165ae836d0bf3deeb4e3f3399dde9c6377bf1f0f1dd5096f5f2f61afad3109e9454521832eeac831cad46ef48a0974487ffb0e5343f387e39d5f40312522ca0d90e51d20c89ff7347a724705f8d4429bb6e27100e603195cf89d38a1a4346721f22704f18b2a9fa001944ebe48b8e08eca91c06c23f13061e5929503d67549526591693da175125eb2d17178",
1116 ]
1117 ];
1118 for vector in vectors {
1119 let bi_commit_bytes =
1121 hex::decode(vector[0]).map_err(|err| eyre!("invalid msg hex bytes: {}", err))?;
1122 let bi_commit = BivarCommitment::from_bytes(bi_commit_bytes)
1123 .expect("invalid bivar commitment bytes");
1124 let row_0 = bi_commit.row(0);
1126 let row_0_hex = &format!("{}", HexFmt(&row_0.to_bytes()));
1127 assert_eq!(row_0_hex, vector[1]);
1128 let row_1 = bi_commit.row(1);
1130 let row_1_hex = &format!("{}", HexFmt(&row_1.to_bytes()));
1131 assert_eq!(row_1_hex, vector[2]);
1132 }
1133
1134 Ok(())
1135 }
1136
1137 #[test]
1138 fn test_bivar_commitment_to_from_bytes_large_degree() {
1139 let mut rng = rand::thread_rng();
1141 let degree = 9; let bi_poly = BivarPoly::random(degree, &mut rng);
1143 let bi_commit = bi_poly.commitment();
1144 let bi_commit_bytes = bi_commit.to_bytes();
1145 let dp1 = degree + 1;
1146 let sum = dp1 * (dp1 + 1) / 2; let expected_size = sum * 48;
1148 assert_eq!(bi_commit_bytes.len(), expected_size);
1149 }
1150
1151 #[test]
1152 fn test_poly_to_from_bytes() {
1153 let degree = 3;
1154 let mut rng = rand::thread_rng();
1155 let poly = Poly::random(degree, &mut rng);
1156 let poly_bytes = poly.to_bytes();
1158 assert_eq!(poly_bytes.len(), (degree + 1) * 32);
1159 let fr = poly.evaluate(0);
1161 let fr_bytes = fr.to_bytes_be();
1162 let fr_bytes_size = fr_bytes.len();
1163 for i in 0..fr_bytes_size {
1164 assert_eq!(fr_bytes[i], poly_bytes[i]);
1165 }
1166 let restored_poly = Poly::from_bytes(poly_bytes).expect("invalid poly bytes");
1168 assert_eq!(poly, restored_poly);
1169 }
1171
1172 #[test]
1173 fn test_bivar_poly_to_from_bytes() {
1174 let degree = 3;
1175 let mut rng = rand::thread_rng();
1176 let bi_poly = BivarPoly::random(degree, &mut rng);
1177 let bi_poly_bytes = bi_poly.to_bytes();
1179 let dp1 = degree + 1;
1180 let sum = dp1 * (dp1 + 1) / 2; let expected_size = sum * SK_SIZE;
1182 assert_eq!(bi_poly_bytes.len(), expected_size);
1183 let poly = bi_poly.row(0);
1185 let poly_bytes = poly.to_bytes();
1186 for i in 0..SK_SIZE {
1187 assert_eq!(poly_bytes[i], bi_poly_bytes[i]);
1188 }
1189 let restored_bi_poly = BivarPoly::from_bytes(bi_poly_bytes).expect("invalid bipoly bytes");
1191 assert_eq!(bi_poly.reveal(), restored_bi_poly.reveal());
1193 for i in 0..10 {
1195 assert_eq!(bi_poly.row(i), restored_bi_poly.row(i));
1196 }
1197 }
1198
1199 #[test]
1200 fn test_bivar_poly_to_from_bytes_large_degree() {
1201 let mut rng = rand::thread_rng();
1202 let degree = 9; let bi_poly = BivarPoly::random(degree, &mut rng);
1204 let bi_poly_bytes = bi_poly.to_bytes();
1205 let dp1 = degree + 1;
1206 let sum = dp1 * (dp1 + 1) / 2; let expected_size = sum * SK_SIZE;
1208 assert_eq!(bi_poly_bytes.len(), expected_size);
1209 }
1210
1211 #[test]
1212 fn vectors_bivar_poly_to_from_bytes() -> Result<()> {
1213 let vectors = vec![
1214 vec![
1217 "016088115a0e8748a29b4bd8dd930692b86241405844f0bbd2fcafb6b4f03880222caa92f7eea1dd8a0e4f2d1e62672a5c12dfcb86199515d4a450ed7921d7ca1407dec2b53c472ffcaf4dbfcd8fe5089cb64a7b5ce7e38655aa97400a3bc1bb4045160918bad84c11afc883e514321009a113cb9bc3b7b941486ec3ca4a273565951ee649287a5809bc0036b8ffee73eb51dc4e3f35e7578169e66823da066672c4060b5f46f15eb1a7c253bb564d9ad2e9c12182a0df61499788817d21a133",
1219 "016088115a0e8748a29b4bd8dd930692b86241405844f0bbd2fcafb6b4f03880222caa92f7eea1dd8a0e4f2d1e62672a5c12dfcb86199515d4a450ed7921d7ca4045160918bad84c11afc883e514321009a113cb9bc3b7b941486ec3ca4a2735",
1221 "63d248ad6ab801723e596389e1099fcd1e1634d77a223d8ae8e96f67f85c377f27dc00e8ccb5e61d5d3fc51b9b5062a1905d6292223903f4abb8ce96a7379fea30c2ec546def4972669fdafe4626be14206169355d9dc6740c49ddaf6b45cecc",
1223 ],
1224 ];
1225 for vector in vectors {
1226 let bi_poly_bytes =
1228 hex::decode(vector[0]).map_err(|err| eyre!("invalid msg hex bytes: {}", err))?;
1229 let bi_poly = BivarPoly::from_bytes(bi_poly_bytes).expect("invalid bipoly bytes");
1230 let row_0 = bi_poly.row(0);
1232 let row_0_hex = &format!("{}", HexFmt(&row_0.to_bytes()));
1233 assert_eq!(row_0_hex, vector[1]);
1234 let row_1 = bi_poly.row(1);
1236 let row_1_hex = &format!("{}", HexFmt(&row_1.to_bytes()));
1237 assert_eq!(row_1_hex, vector[2]);
1238 }
1239
1240 Ok(())
1241 }
1242}