1use alloc::{vec, vec::Vec};
5use core::{
6 fmt::Debug,
7 hash::{Hash, Hasher},
8 ops::{Deref, DerefMut},
9};
10
11use elliptic_curve::{
12 group::GroupEncoding, CurveArithmetic, Field, Group, NonZeroScalar,
13 PrimeField,
14};
15use rand_core::CryptoRngCore;
16
17use crate::matrix::matrix_inverse;
18
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21#[cfg_attr(
22 feature = "serde",
23 serde(bound(
24 serialize = "G::Scalar: serde::Serialize",
25 deserialize = "G::Scalar: serde::de::DeserializeOwned"
26 ))
27)]
28#[derive(PartialEq, Eq)]
29pub struct Polynomial<G>
30where
31 G: Group,
32 G::Scalar: ser::Serializable,
33{
34 coeffs: Vec<G::Scalar>,
35}
36
37impl<G> Hash for Polynomial<G>
38where
39 G: Group,
40 G::Scalar: Hash + ser::Serializable,
41{
42 fn hash<H: Hasher>(&self, state: &mut H) {
43 self.coeffs.hash(state);
44 }
45}
46
47#[cfg(test)]
48impl<G> Debug for Polynomial<G>
49where
50 G: Group,
51 G::Scalar: ser::Serializable,
52{
53 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54 f.debug_struct("Polynomial")
55 .field("len", &self.coeffs.len())
56 .finish()
57 }
58}
59
60impl<G> Polynomial<G>
61where
62 G: Group,
63 G::Scalar: ser::Serializable,
64{
65 pub fn new(coeffs: Vec<G::Scalar>) -> Self {
67 Self { coeffs }
68 }
69
70 pub fn random(rng: &mut impl CryptoRngCore, degree: usize) -> Self {
72 Self {
73 coeffs: (0..=degree)
74 .map(|_| G::Scalar::random(&mut *rng))
75 .collect(),
76 }
77 }
78
79 pub fn reset_contant(&mut self) {
81 self.coeffs[0] = G::Scalar::ZERO;
82 }
83
84 pub fn reset_constant(&mut self) {
86 self.coeffs[0] = G::Scalar::ZERO;
87 }
88
89 pub fn set_constant(&mut self, scalar: G::Scalar) {
91 self.coeffs[0] = scalar;
92 }
93
94 pub fn get_constant(&self) -> &G::Scalar {
96 &self.coeffs[0]
97 }
98
99 pub fn commit(&self) -> GroupPolynomial<G>
101 where
102 G: GroupEncoding,
103 {
104 GroupPolynomial::new(
105 self.coeffs
106 .iter()
107 .map(|coeff| G::generator() * coeff)
108 .collect(),
109 )
110 }
111
112 pub fn derivative_at(&self, n: usize, x: &G::Scalar) -> G::Scalar {
119 self.coeffs
120 .iter()
121 .enumerate()
122 .skip(n)
123 .map(|(i, coeff)| {
124 let scalar_num: G::Scalar = factorial_range(i - n, i);
125 let result = x.pow_vartime([(i - n) as u64]);
126
127 scalar_num * coeff * result
128 })
129 .sum()
130 }
131
132 pub fn evaluate_at(&self, x: &G::Scalar) -> G::Scalar {
137 self.coeffs
138 .iter()
139 .enumerate()
140 .map(|(i, coeff)| {
141 let result = x.pow_vartime([i as u64]);
142 result * coeff
143 })
144 .sum()
145 }
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Default)]
150pub struct GroupPolynomial<G>
151where
152 G: Group + GroupEncoding,
153{
154 pub coeffs: Vec<G>,
155}
156
157impl<G: Group + GroupEncoding> From<GroupPolynomial<G>> for Vec<G> {
158 fn from(p: GroupPolynomial<G>) -> Vec<G> {
159 p.coeffs
160 }
161}
162
163impl<G> Deref for GroupPolynomial<G>
164where
165 G: Group + GroupEncoding,
166{
167 type Target = [G];
168
169 fn deref(&self) -> &Self::Target {
170 &self.coeffs
171 }
172}
173
174impl<G> DerefMut for GroupPolynomial<G>
175where
176 G: Group + GroupEncoding,
177{
178 fn deref_mut(&mut self) -> &mut Self::Target {
179 &mut self.coeffs
180 }
181}
182
183impl<G> AsRef<[G]> for GroupPolynomial<G>
184where
185 G: Group + GroupEncoding,
186{
187 fn as_ref(&self) -> &[G] {
188 &self.coeffs
189 }
190}
191
192impl<G> GroupPolynomial<G>
193where
194 G: Group + GroupEncoding,
195{
196 pub fn new(coeffs: Vec<G>) -> Self {
198 Self { coeffs }
199 }
200
201 pub fn identity(size: usize) -> Self {
202 Self {
203 coeffs: vec![G::identity(); size],
204 }
205 }
206
207 pub fn get_constant(&self) -> G {
209 self.coeffs[0]
210 }
211
212 pub fn add_mut<T>(&mut self, other: T)
216 where
217 T: AsRef<[G]>,
218 {
219 self.coeffs
220 .iter_mut()
221 .zip(other.as_ref())
222 .for_each(|(a, b)| {
223 *a += b;
224 });
225 }
226
227 pub fn derivative_coeffs(&self, n: usize) -> impl Iterator<Item = G> + '_
229 where
230 G: Group,
231 {
232 self.coeffs[n..]
233 .iter()
234 .enumerate()
235 .map(move |(position, &u_i)| {
236 u_i * factorial_range::<G::Scalar>(position, position + n)
237 })
238 }
239
240 pub fn points(&self) -> impl Iterator<Item = &'_ G> {
241 self.coeffs.iter()
242 }
243
244 pub fn get(&self, idx: usize) -> Option<&G> {
245 self.coeffs.get(idx)
246 }
247
248 pub fn evaluate_at(&self, x: &G::Scalar) -> G
249 where
250 G: Group,
251 {
252 let init = (G::identity(), G::Scalar::ONE);
253
254 let (p, _) = self.coeffs.iter().fold(init, |(s, x_pow_i), &coeff| {
255 (s + coeff * x_pow_i, x_pow_i * x)
256 });
257
258 p
259 }
260}
261
262impl<G> Deref for Polynomial<G>
263where
264 G: Group,
265 G::Scalar: ser::Serializable,
266{
267 type Target = [G::Scalar];
268
269 fn deref(&self) -> &Self::Target {
270 &self.coeffs
271 }
272}
273
274pub fn factorial<S: PrimeField>(n: usize) -> S {
276 factorial_range(0, n)
277}
278
279const fn small_factorial<const N: usize>() -> [u64; N] {
280 let mut a = [1u64; N];
281
282 let mut j = 1;
283
284 while j < N {
285 a[j] = j as u64 * a[j - 1];
286 j += 1;
287 }
288
289 a
290}
291
292static FACT: [u64; 21] = small_factorial();
294
295pub fn factorial_range<S: PrimeField>(start: usize, end: usize) -> S {
297 debug_assert!(start <= end);
298
299 if end < FACT.len() {
300 return S::from(FACT[end] / FACT[start]);
301 }
302
303 (start + 1..=end).fold(S::ONE, |acc, x| acc * S::from(x as u64))
304}
305
306pub fn feldman_verify<C: CurveArithmetic>(
308 u_i_k: impl Iterator<Item = C::ProjectivePoint>,
309 x_i: &NonZeroScalar<C>,
310 f_i_value: &C::Scalar,
311 g: &C::ProjectivePoint,
312) -> bool {
313 let x_i = x_i as &C::Scalar;
314 let one = C::Scalar::ONE;
315 let s = C::ProjectivePoint::identity();
316
317 let (point, _) = u_i_k
319 .fold((s, one), |(sum, val), coeff| (sum + coeff * val, val * x_i));
320
321 if point.is_identity().into() {
322 return false;
323 }
324
325 let expected_point = *g * f_i_value;
326
327 point == expected_point
328}
329
330pub fn polynomial_coeff_multipliers_iter<C>(
331 x_i: &NonZeroScalar<C>,
332 n_i: usize,
333 n: usize,
334) -> impl Iterator<Item = C::Scalar> + '_
335where
336 C: CurveArithmetic,
337{
338 (0..n).map(move |idx| {
339 if idx < n_i {
340 C::Scalar::ZERO
341 } else {
342 let num: C::Scalar = factorial_range(idx - n_i, idx);
343 let exponent = [(idx - n_i) as u64];
344 let result = x_i.pow_vartime(exponent);
345
346 num * result
347 }
348 })
349}
350
351pub fn polynomial_coeff_multipliers<C>(
356 x_i: &NonZeroScalar<C>,
357 n_i: usize,
358 n: usize,
359) -> Vec<C::Scalar>
360where
361 C: CurveArithmetic,
362{
363 polynomial_coeff_multipliers_iter(x_i, n_i, n).collect()
364}
365
366pub fn birkhoff_coeffs<C>(
368 params: &[(NonZeroScalar<C>, usize)],
369) -> Vec<C::Scalar>
370where
371 C: CurveArithmetic,
372{
373 let n = params.len();
374
375 let matrix: Vec<Vec<C::Scalar>> = params
376 .iter()
377 .map(|(x_i, n_i)| polynomial_coeff_multipliers(x_i, *n_i, n))
378 .collect();
379
380 matrix_inverse::<C>(matrix, n).swap_remove(0)
381}
382
383#[cfg(not(feature = "serde"))]
384mod ser {
385 pub trait Serializable {}
386 impl<T> Serializable for T {}
387}
388
389#[cfg(feature = "serde")]
390mod ser {
391 use super::*;
392
393 pub trait Serializable:
394 serde::Serialize + serde::de::DeserializeOwned
395 {
396 }
397
398 impl<T: serde::Serialize + serde::de::DeserializeOwned> Serializable for T {}
399
400 impl<G> serde::Serialize for GroupPolynomial<G>
401 where
402 G: Group + GroupEncoding,
403 {
404 fn serialize<S>(
405 &self,
406 serializer: S,
407 ) -> core::result::Result<S::Ok, S::Error>
408 where
409 S: serde::ser::Serializer,
410 {
411 use serde::ser::SerializeSeq;
412
413 let mut seq =
414 serializer.serialize_seq(Some(self.coeffs.len()))?;
415 for coeff in &self.coeffs {
416 seq.serialize_element(&coeff.to_bytes().as_ref())?;
417 }
418 seq.end()
419 }
420 }
421
422 impl<'de, G> serde::Deserialize<'de> for GroupPolynomial<G>
423 where
424 G: Group + GroupEncoding,
425 {
426 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
427 where
428 D: serde::de::Deserializer<'de>,
429 {
430 let data: Vec<Vec<u8>> =
431 serde::Deserialize::deserialize(deserializer)?;
432 let mut coeffs = Vec::with_capacity(data.len());
433
434 for coeff_data in &data {
435 let repr = G::Repr::default();
436 if coeff_data.len() != repr.as_ref().len() {
437 return Err(serde::de::Error::custom(
438 "Invalid group element",
439 ));
440 }
441 let mut repr = repr;
442 repr.as_mut().copy_from_slice(coeff_data);
443 let opt = G::from_bytes(&repr);
444
445 let point = if opt.is_some().into() {
446 opt.unwrap()
447 } else {
448 return Err(serde::de::Error::custom(
449 "Invalid group element",
450 ));
451 };
452 coeffs.push(point);
453 }
454
455 Ok(Self { coeffs })
456 }
457 }
458}
459
460#[cfg(test)]
461mod tests {
462 use elliptic_curve::{scalar::FromUintUnchecked, Curve};
463 use k256::{ProjectivePoint, Scalar, Secp256k1};
464
465 use super::*;
466
467 #[test]
468 #[cfg(feature = "serde")]
469 fn test_serde() {
470 use super::*;
471 use k256::ProjectivePoint;
472
473 let mut rng = rand::thread_rng();
474 let poly1 = Polynomial::<ProjectivePoint>::random(&mut rng, 5);
475 let mut bytes = Vec::new();
476 ciborium::into_writer(&poly1, &mut bytes).unwrap();
477 let poly2: Polynomial<ProjectivePoint> =
478 ciborium::from_reader(bytes.as_slice()).unwrap();
479
480 let g_poly1 = poly1.commit();
481
482 let mut bytes = Vec::new();
483 ciborium::into_writer(&g_poly1, &mut bytes).unwrap();
484
485 let g_poly2: GroupPolynomial<ProjectivePoint> =
486 ciborium::from_reader(bytes.as_slice()).unwrap();
487
488 assert_eq!(poly1, poly2);
489 assert_eq!(g_poly1, g_poly2);
490 }
491
492 #[test]
493 fn fact() {
494 assert_eq!(FACT[19], 121645100408832000);
497 assert_eq!(FACT[20], 2432902008176640000); }
499
500 #[test]
501 fn test_derivative_large() {
502 let order = Secp256k1::ORDER;
504 let u_i_k = vec![
507 Scalar::from(1_u64),
508 Scalar::from(2_u64),
509 Scalar::from_uint_unchecked(order.wrapping_sub(&1u64.into())),
510 ];
511
512 let poly = Polynomial::<ProjectivePoint>::new(u_i_k);
515 let n = 1;
516
517 let result = poly.derivative_at(n, &Scalar::from(2_u64));
518
519 assert_eq!(
520 result,
521 Scalar::from_uint_unchecked(order.wrapping_sub(&2u64.into()))
522 );
523 }
524
525 #[test]
526 fn test_derivative_normal() {
527 let u_i_k = vec![
529 Scalar::from(1_u64),
530 Scalar::from(2_u64),
531 Scalar::from(3_u64),
532 Scalar::from(4_u64),
533 ];
534
535 let poly = Polynomial::<ProjectivePoint>::new(u_i_k);
536
537 let n = 2;
539 let result = poly.derivative_at(n, &Scalar::from(2_u64));
541
542 assert_eq!(result, Scalar::from(54_u64));
543 }
544
545 #[test]
546 fn test_derivative_coeffs() {
547 let g = ProjectivePoint::GENERATOR;
549 let u_i_k = vec![
550 (g * Scalar::from(1_u64)),
551 (g * Scalar::from(2_u64)),
552 (g * Scalar::from(3_u64)),
553 (g * Scalar::from(4_u64)),
554 ];
555
556 let poly = GroupPolynomial::<ProjectivePoint>::new(u_i_k);
557
558 let n = 2;
560 let coeffs = poly.derivative_coeffs(n).collect::<Vec<_>>();
561
562 assert_eq!(coeffs.len(), 2);
563 assert_eq!(coeffs[0], g * Scalar::from(6_u64));
564 assert_eq!(coeffs[1], g * Scalar::from(24_u64));
565
566 let coeffs = poly.derivative_coeffs(1).collect::<Vec<_>>();
568
569 assert_eq!(coeffs.len(), 3);
570 assert_eq!(coeffs[0], g * Scalar::from(2_u64));
571 assert_eq!(coeffs[1], g * Scalar::from(6_u64));
572 assert_eq!(coeffs[2], g * Scalar::from(12_u64));
573 }
574}