|  |  |  | @ -19,7 +19,7 @@ | 
			
		
	
		
			
				
					|  |  |  |  | use std::borrow::Borrow; | 
			
		
	
		
			
				
					|  |  |  |  | use std::fmt::{self, Debug, Formatter}; | 
			
		
	
		
			
				
					|  |  |  |  | use std::hash::{Hash, Hasher}; | 
			
		
	
		
			
				
					|  |  |  |  | use std::mem::{size_of, size_of_val}; | 
			
		
	
		
			
				
					|  |  |  |  | use std::mem::size_of_val; | 
			
		
	
		
			
				
					|  |  |  |  | use std::{cmp, iter, ops}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use errno::errno; | 
			
		
	
	
		
			
				
					|  |  |  | @ -28,7 +28,7 @@ use pairing::bls12_381::{Fr, G1Affine, G1}; | 
			
		
	
		
			
				
					|  |  |  |  | use pairing::{CurveAffine, CurveProjective, Field}; | 
			
		
	
		
			
				
					|  |  |  |  | use rand::Rng; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | use super::{ContainsSecret, Error, IntoFr, Result, SHOULD_MLOCK_SECRETS}; | 
			
		
	
		
			
				
					|  |  |  |  | use super::{clear_fr, ContainsSecret, Error, IntoFr, Result, FR_SIZE, SHOULD_MLOCK_SECRETS}; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /// A univariate polynomial in the prime field.
 | 
			
		
	
		
			
				
					|  |  |  |  | #[derive(Serialize, Deserialize, PartialEq, Eq)] | 
			
		
	
	
		
			
				
					|  |  |  | @ -46,10 +46,8 @@ pub struct Poly { | 
			
		
	
		
			
				
					|  |  |  |  | /// `Poly`.
 | 
			
		
	
		
			
				
					|  |  |  |  | impl Clone for Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     fn clone(&self) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         match Poly::new(self.coeff.clone()) { | 
			
		
	
		
			
				
					|  |  |  |  |             Ok(poly) => poly, | 
			
		
	
		
			
				
					|  |  |  |  |             Err(e) => panic!("Failed to clone `Poly`: {}", e), | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_from(self.coeff.clone()) | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap_or_else(|e| panic!("Failed to clone `Poly`: {}", e)) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -213,7 +211,7 @@ impl<'a, B: Borrow<Poly>> ops::Mul<B> for &'a Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     fn mul(self, rhs: B) -> Self::Output { | 
			
		
	
		
			
				
					|  |  |  |  |         let rhs = rhs.borrow(); | 
			
		
	
		
			
				
					|  |  |  |  |         if rhs.coeff.is_empty() || self.coeff.is_empty() { | 
			
		
	
		
			
				
					|  |  |  |  |             return Poly::zero().expect("failed to create zero Poly"); | 
			
		
	
		
			
				
					|  |  |  |  |             return Poly::zero(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         let mut coeff = vec![Fr::zero(); self.coeff.len() + rhs.borrow().coeff.len() - 1]; | 
			
		
	
		
			
				
					|  |  |  |  |         let mut s; // TODO: Mlock and zero on drop.
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -224,9 +222,8 @@ impl<'a, B: Borrow<Poly>> ops::Mul<B> for &'a Poly { | 
			
		
	
		
			
				
					|  |  |  |  |                 coeff[i + j].add_assign(&s); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::new(coeff).unwrap_or_else(|e| { | 
			
		
	
		
			
				
					|  |  |  |  |             panic!("Failed to create a new `Poly` during muliplication: {}", e); | 
			
		
	
		
			
				
					|  |  |  |  |         }) | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_from(coeff) | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap_or_else(|e| panic!("Failed to create a new `Poly` during muliplication: {}", e)) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -247,7 +244,7 @@ impl<B: Borrow<Self>> ops::MulAssign<B> for Poly { | 
			
		
	
		
			
				
					|  |  |  |  | impl ops::MulAssign<Fr> for Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     fn mul_assign(&mut self, rhs: Fr) { | 
			
		
	
		
			
				
					|  |  |  |  |         if rhs.is_zero() { | 
			
		
	
		
			
				
					|  |  |  |  |             *self = Poly::zero().expect("failed to create zero Poly"); | 
			
		
	
		
			
				
					|  |  |  |  |             *self = Poly::zero(); | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             for c in &mut self.coeff { | 
			
		
	
		
			
				
					|  |  |  |  |                 c.mul_assign(&rhs); | 
			
		
	
	
		
			
				
					|  |  |  | @ -322,6 +319,19 @@ impl Drop for Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /// Creates a new `Poly` instance from a vector of prime field elements representing the
 | 
			
		
	
		
			
				
					|  |  |  |  | /// coefficients of the polynomial. We lock the region of the heap where the polynomial
 | 
			
		
	
		
			
				
					|  |  |  |  | /// coefficients are allocated.
 | 
			
		
	
		
			
				
					|  |  |  |  | ///
 | 
			
		
	
		
			
				
					|  |  |  |  | /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  | ///
 | 
			
		
	
		
			
				
					|  |  |  |  | /// Panics if we have reached the system's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  | impl From<Vec<Fr>> for Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     fn from(coeffs: Vec<Fr>) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_from(coeffs).unwrap_or_else(|e| panic!("Failed to create `Poly`: {}", e)) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl ContainsSecret for Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     fn mlock_secret_memory(&self) -> Result<()> { | 
			
		
	
		
			
				
					|  |  |  |  |         if !*SHOULD_MLOCK_SECRETS { | 
			
		
	
	
		
			
				
					|  |  |  | @ -378,80 +388,167 @@ impl ContainsSecret for Poly { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     /// Creates a new `Poly` instance from a vector of prime field elements representing the
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// coefficients of the polynomial. The `mlock` system call is applied to the region of the
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// heap where the field elements are allocated.
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// coefficients of the polynomial. We lock the region of the heap where the polynomial
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// coefficients are allocated.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn new(coeff: Vec<Fr>) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_from(coeff: Vec<Fr>) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         let poly = Poly { coeff }; | 
			
		
	
		
			
				
					|  |  |  |  |         poly.mlock_secret_memory()?; | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(poly) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Creates a random polynomial.
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Creates a random polynomial. This constructor is identical to the `Poly::try_random()`
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// constructor in every way except that this constructor will panic if locking the polynomial
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// coefficients into RAM fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have reached the system's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn random<R: Rng>(degree: usize, rng: &mut R) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_random(degree, rng) | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap_or_else(|e| panic!("Failed to create random `Poly`: {}", e)) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Creates a random polynomial. This constructor is identical to the `Poly::random()`
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// constructor in every way except that this constructor will return an `Err` if locking the
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// polynomial coefficients into RAM fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn random<R: Rng>(degree: usize, rng: &mut R) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_random<R: Rng>(degree: usize, rng: &mut R) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         let coeff: Vec<Fr> = (0..=degree).map(|_| rng.gen()).collect(); | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::new(coeff) | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_from(coeff) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the polynomial with constant value `0`.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// This constructor does not return a `Result` because the polynomial's `coeff` vector is
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// empty, which does not require memory locking. Memory locking will occur when the first
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// coefficient is added to the `coeff` vector.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn zero() -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly { coeff: vec![] } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the polynomial with constant value `1`. This constructor is identical to
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// `Poly::try_one()` in every way except that this constructor panics if locking the `coeff`
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// vector into RAM fails, whereas `Poly::try_one()` returns an `Err`.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn zero() -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::new(vec![]) | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have reached the system's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn one() -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_one() | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap_or_else(|e| panic!("Failed to create constant `Poly` of value 1: {}", e)) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the polynomial with constant value `1`.
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the polynomial with constant value `1`. This constructor is identical to
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// `Poly::one()` in every way except that this constructor returns `Err` if locking the
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// `coeff` vector into RAM fails, whereas `Poly::one()` panics.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn one() -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         Self::monomial(0) | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_one() -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_constant(Fr::one()) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the polynomial with constant value `c`. Panics if memory locking fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn constant(c: Fr) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         // We create a raw pointer to the field element within this method's stack frame so we can
 | 
			
		
	
		
			
				
					|  |  |  |  |         // overwrite that portion of memory with zeros once we have copied the element onto the
 | 
			
		
	
		
			
				
					|  |  |  |  |         // heap as part of the vector of polynomial coefficients.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let fr_ptr = &c as *const Fr as *mut u8; | 
			
		
	
		
			
				
					|  |  |  |  |         let poly = Poly::try_from(vec![c]) | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap_or_else(|e| panic!("Failed to create constant `Poly`: {}", e)); | 
			
		
	
		
			
				
					|  |  |  |  |         clear_fr(fr_ptr); | 
			
		
	
		
			
				
					|  |  |  |  |         poly | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the polynomial with constant value `c`.
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the polynomial with constant value `c`. This constructor is identical to
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// `Poly::constant()` in every way except that this constructor returns an `Err` if locking
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// the polynomial coefficients into RAM fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn constant(c: Fr) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         let ptr = &c as *const Fr as *mut u8; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = Poly::new(vec![c]); | 
			
		
	
		
			
				
					|  |  |  |  |         unsafe { | 
			
		
	
		
			
				
					|  |  |  |  |             memzero(ptr, size_of::<Fr>()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_constant(c: Fr) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         // We create a raw pointer to the field element within this method's stack frame so we can
 | 
			
		
	
		
			
				
					|  |  |  |  |         // overwrite that portion of memory with zeros once we have copied the element onto the
 | 
			
		
	
		
			
				
					|  |  |  |  |         // heap as part of polynomials `coeff` vector.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let fr_ptr = &c as *const Fr as *mut u8; | 
			
		
	
		
			
				
					|  |  |  |  |         let res = Poly::try_from(vec![c]); | 
			
		
	
		
			
				
					|  |  |  |  |         clear_fr(fr_ptr); | 
			
		
	
		
			
				
					|  |  |  |  |         res | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the identity function, i.e. the polynomial "`x`".
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the identity function, i.e. the polynomial "`x`". Panics if mlocking fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have reached the system's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn identity() -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::monomial(1) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the identity function, i.e. the polynomial `x`. Returns an `Err` if mlocking
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn identity() -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         Self::monomial(1) | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_identity() -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_monomial(1) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the (monic) monomial "`x.pow(degree)`"
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the (monic) monomial: `x.pow(degree)`. Panics if mlocking fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn monomial(degree: usize) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_monomial(degree).unwrap_or_else(|e| { | 
			
		
	
		
			
				
					|  |  |  |  |             panic!( | 
			
		
	
		
			
				
					|  |  |  |  |                 "Failed to create monomial `Poly` of degree {}: {}", | 
			
		
	
		
			
				
					|  |  |  |  |                 degree, e | 
			
		
	
		
			
				
					|  |  |  |  |             ) | 
			
		
	
		
			
				
					|  |  |  |  |         }) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the (monic) monomial: `x.pow(degree)`. Returns an `Err` if mlocking fails.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn monomial(degree: usize) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_monomial(degree: usize) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         let coeff: Vec<Fr> = iter::repeat(Fr::zero()) | 
			
		
	
		
			
				
					|  |  |  |  |             .take(degree) | 
			
		
	
		
			
				
					|  |  |  |  |             .chain(iter::once(Fr::one())) | 
			
		
	
		
			
				
					|  |  |  |  |             .collect(); | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::new(coeff) | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_from(coeff) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the unique polynomial `f` of degree `samples.len() - 1` with the given values
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// `(x, f(x))`.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn interpolate<T, U, I>(samples_repr: I) -> Self | 
			
		
	
		
			
				
					|  |  |  |  |     where | 
			
		
	
		
			
				
					|  |  |  |  |         I: IntoIterator<Item = (T, U)>, | 
			
		
	
		
			
				
					|  |  |  |  |         T: IntoFr, | 
			
		
	
		
			
				
					|  |  |  |  |         U: IntoFr, | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_interpolate(samples_repr) | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap_or_else(|e| panic!("Failed to interpolate `Poly`: {}", e)) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the unique polynomial `f` of degree `samples.len() - 1` with the given values
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -460,7 +557,7 @@ impl Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn interpolate<T, U, I>(samples_repr: I) -> Result<Self> | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_interpolate<T, U, I>(samples_repr: I) -> Result<Self> | 
			
		
	
		
			
				
					|  |  |  |  |     where | 
			
		
	
		
			
				
					|  |  |  |  |         I: IntoIterator<Item = (T, U)>, | 
			
		
	
		
			
				
					|  |  |  |  |         T: IntoFr, | 
			
		
	
	
		
			
				
					|  |  |  | @ -468,7 +565,7 @@ impl Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     { | 
			
		
	
		
			
				
					|  |  |  |  |         let convert = |(x, y): (T, U)| (x.into_fr(), y.into_fr()); | 
			
		
	
		
			
				
					|  |  |  |  |         let samples: Vec<(Fr, Fr)> = samples_repr.into_iter().map(convert).collect(); | 
			
		
	
		
			
				
					|  |  |  |  |         Self::compute_interpolation(&samples) | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::compute_interpolation(&samples) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the degree.
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -516,19 +613,17 @@ impl Poly { | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we hit the system's locked memory limit and failed to
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// `mlock` the new `Poly` instance.
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we hit the system's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     fn compute_interpolation(samples: &[(Fr, Fr)]) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         let mut poly; // Interpolates on the first `i` samples.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut base; // Is zero on the first `i` samples.
 | 
			
		
	
		
			
				
					|  |  |  |  |         if samples.is_empty() { | 
			
		
	
		
			
				
					|  |  |  |  |             return Poly::zero(); | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             poly = Poly::constant(samples[0].1)?; | 
			
		
	
		
			
				
					|  |  |  |  |             let mut minus_s0 = samples[0].0; | 
			
		
	
		
			
				
					|  |  |  |  |             minus_s0.negate(); | 
			
		
	
		
			
				
					|  |  |  |  |             base = Poly::new(vec![minus_s0, Fr::one()])?; | 
			
		
	
		
			
				
					|  |  |  |  |             return Ok(Poly::zero()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         // Interpolates on the first `i` samples.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut poly = Poly::try_constant(samples[0].1)?; | 
			
		
	
		
			
				
					|  |  |  |  |         let mut minus_s0 = samples[0].0; | 
			
		
	
		
			
				
					|  |  |  |  |         minus_s0.negate(); | 
			
		
	
		
			
				
					|  |  |  |  |         // Is zero on the first `i` samples.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut base = Poly::try_from(vec![minus_s0, Fr::one()])?; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // We update `base` so that it is always zero on all previous samples, and `poly` so that
 | 
			
		
	
		
			
				
					|  |  |  |  |         // it has the correct values on the previous samples.
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -545,7 +640,7 @@ impl Poly { | 
			
		
	
		
			
				
					|  |  |  |  |             // Finally, multiply `base` by X - x, so that it is zero at `x`, too, now.
 | 
			
		
	
		
			
				
					|  |  |  |  |             let mut minus_x = *x; | 
			
		
	
		
			
				
					|  |  |  |  |             minus_x.negate(); | 
			
		
	
		
			
				
					|  |  |  |  |             base *= Poly::new(vec![minus_x, Fr::one()])?; | 
			
		
	
		
			
				
					|  |  |  |  |             base *= Poly::try_from(vec![minus_x, Fr::one()])?; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         Ok(poly) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  |  | @ -555,7 +650,7 @@ impl Poly { | 
			
		
	
		
			
				
					|  |  |  |  |         if !*SHOULD_MLOCK_SECRETS { | 
			
		
	
		
			
				
					|  |  |  |  |             return Ok(()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         let n_bytes_truncated = len * size_of::<Fr>(); | 
			
		
	
		
			
				
					|  |  |  |  |         let n_bytes_truncated = *FR_SIZE * len; | 
			
		
	
		
			
				
					|  |  |  |  |         if n_bytes_truncated == 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             return Ok(()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -580,7 +675,7 @@ impl Poly { | 
			
		
	
		
			
				
					|  |  |  |  |         if !*SHOULD_MLOCK_SECRETS { | 
			
		
	
		
			
				
					|  |  |  |  |             return Ok(()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         let n_bytes_extended = len * size_of::<Fr>(); | 
			
		
	
		
			
				
					|  |  |  |  |         let n_bytes_extended = *FR_SIZE * len; | 
			
		
	
		
			
				
					|  |  |  |  |         if n_bytes_extended == 0 { | 
			
		
	
		
			
				
					|  |  |  |  |             return Ok(()); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | @ -788,12 +883,26 @@ impl ContainsSecret for BivarPoly { | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | impl BivarPoly { | 
			
		
	
		
			
				
					|  |  |  |  |     /// Creates a random polynomial.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have hit the system's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn random<R: Rng>(degree: usize, rng: &mut R) -> Self { | 
			
		
	
		
			
				
					|  |  |  |  |         BivarPoly::try_random(degree, rng).unwrap_or_else(|e| { | 
			
		
	
		
			
				
					|  |  |  |  |             panic!( | 
			
		
	
		
			
				
					|  |  |  |  |                 "Failed to create random `BivarPoly` of degree {}: {}", | 
			
		
	
		
			
				
					|  |  |  |  |                 degree, e | 
			
		
	
		
			
				
					|  |  |  |  |             ) | 
			
		
	
		
			
				
					|  |  |  |  |         }) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Creates a random polynomial.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn random<R: Rng>(degree: usize, rng: &mut R) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_random<R: Rng>(degree: usize, rng: &mut R) -> Result<Self> { | 
			
		
	
		
			
				
					|  |  |  |  |         let poly = BivarPoly { | 
			
		
	
		
			
				
					|  |  |  |  |             degree, | 
			
		
	
		
			
				
					|  |  |  |  |             coeff: (0..coeff_pos(degree + 1, 0)).map(|_| rng.gen()).collect(), | 
			
		
	
	
		
			
				
					|  |  |  | @ -824,13 +933,23 @@ impl BivarPoly { | 
			
		
	
		
			
				
					|  |  |  |  |         result | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the `x`-th row, as a univariate polynomial.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Panics
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Panics if we have reached the system's locked memory limit.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn row<T: IntoFr>(&self, x: T) -> Poly { | 
			
		
	
		
			
				
					|  |  |  |  |         self.try_row(x) | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap_or_else(|e| panic!("Failed to create `Poly` from row of `BivarPoly: {}`", e)) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the `x`-th row, as a univariate polynomial.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// # Errors
 | 
			
		
	
		
			
				
					|  |  |  |  |     ///
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns an `Error::MlockFailed` if we have reached the systems's locked memory limit when
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// creating the new `Poly` instance.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn row<T: IntoFr>(&self, x: T) -> Result<Poly> { | 
			
		
	
		
			
				
					|  |  |  |  |     pub fn try_row<T: IntoFr>(&self, x: T) -> Result<Poly> { | 
			
		
	
		
			
				
					|  |  |  |  |         let x_pow = self.powers(x); | 
			
		
	
		
			
				
					|  |  |  |  |         let coeff: Vec<Fr> = (0..=self.degree) | 
			
		
	
		
			
				
					|  |  |  |  |             .map(|i| { | 
			
		
	
	
		
			
				
					|  |  |  | @ -843,7 +962,7 @@ impl BivarPoly { | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |                 result | 
			
		
	
		
			
				
					|  |  |  |  |             }).collect(); | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::new(coeff) | 
			
		
	
		
			
				
					|  |  |  |  |         Poly::try_from(coeff) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /// Returns the corresponding commitment. That information can be shared publicly.
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -985,8 +1104,8 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  |     #[test] | 
			
		
	
		
			
				
					|  |  |  |  |     fn poly() { | 
			
		
	
		
			
				
					|  |  |  |  |         // The polynomial 5 X³ + X - 2.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let x_pow_3 = Poly::monomial(3).expect("Failed to create monic polynomial of degree 3"); | 
			
		
	
		
			
				
					|  |  |  |  |         let x_pow_1 = Poly::monomial(1).expect("Failed to create monic polynomial of degree 1"); | 
			
		
	
		
			
				
					|  |  |  |  |         let x_pow_3 = Poly::monomial(3); | 
			
		
	
		
			
				
					|  |  |  |  |         let x_pow_1 = Poly::monomial(1); | 
			
		
	
		
			
				
					|  |  |  |  |         let poly = x_pow_3 * 5 + x_pow_1 - 2; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let coeff: Vec<_> = [-2, 1, 0, 5].into_iter().map(IntoFr::into_fr).collect(); | 
			
		
	
	
		
			
				
					|  |  |  | @ -995,7 +1114,7 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  |         for &(x, y) in &samples { | 
			
		
	
		
			
				
					|  |  |  |  |             assert_eq!(y.into_fr(), poly.evaluate(x)); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         let interp = Poly::interpolate(samples).expect("Failed to interpolate `Poly`"); | 
			
		
	
		
			
				
					|  |  |  |  |         let interp = Poly::interpolate(samples); | 
			
		
	
		
			
				
					|  |  |  |  |         assert_eq!(interp, poly); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -1010,10 +1129,8 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  |         // generates random bivariate polynomials and publicly commits to them. In partice, the
 | 
			
		
	
		
			
				
					|  |  |  |  |         // dealers can e.g. be any `faulty_num + 1` nodes.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let bi_polys: Vec<BivarPoly> = (0..dealer_num) | 
			
		
	
		
			
				
					|  |  |  |  |             .map(|_| { | 
			
		
	
		
			
				
					|  |  |  |  |                 BivarPoly::random(faulty_num, &mut rng) | 
			
		
	
		
			
				
					|  |  |  |  |                     .expect("Failed to create random `BivarPoly`") | 
			
		
	
		
			
				
					|  |  |  |  |             }).collect(); | 
			
		
	
		
			
				
					|  |  |  |  |             .map(|_| BivarPoly::random(faulty_num, &mut rng)) | 
			
		
	
		
			
				
					|  |  |  |  |             .collect(); | 
			
		
	
		
			
				
					|  |  |  |  |         let pub_bi_commits: Vec<_> = bi_polys.iter().map(BivarPoly::commitment).collect(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut sec_keys = vec![Fr::zero(); node_num]; | 
			
		
	
	
		
			
				
					|  |  |  | @ -1024,9 +1141,7 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  |         for (bi_poly, bi_commit) in bi_polys.iter().zip(&pub_bi_commits) { | 
			
		
	
		
			
				
					|  |  |  |  |             for m in 1..=node_num { | 
			
		
	
		
			
				
					|  |  |  |  |                 // Node `m` receives its row and verifies it.
 | 
			
		
	
		
			
				
					|  |  |  |  |                 let row_poly = bi_poly | 
			
		
	
		
			
				
					|  |  |  |  |                     .row(m) | 
			
		
	
		
			
				
					|  |  |  |  |                     .unwrap_or_else(|_| panic!("Failed to create row #{}", m)); | 
			
		
	
		
			
				
					|  |  |  |  |                 let row_poly = bi_poly.row(m); | 
			
		
	
		
			
				
					|  |  |  |  |                 let row_commit = bi_commit.row(m); | 
			
		
	
		
			
				
					|  |  |  |  |                 assert_eq!(row_poly.commitment(), row_commit); | 
			
		
	
		
			
				
					|  |  |  |  |                 // Node `s` receives the `s`-th value and verifies it.
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -1039,10 +1154,8 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // A cheating dealer who modified the polynomial would be detected.
 | 
			
		
	
		
			
				
					|  |  |  |  |                 let x_pow_2 = | 
			
		
	
		
			
				
					|  |  |  |  |                     Poly::monomial(2).expect("Failed to create monic polynomial of degree 2"); | 
			
		
	
		
			
				
					|  |  |  |  |                 let five = Poly::constant(5.into_fr()) | 
			
		
	
		
			
				
					|  |  |  |  |                     .expect("Failed to create polynomial with constant 5"); | 
			
		
	
		
			
				
					|  |  |  |  |                 let x_pow_2 = Poly::monomial(2); | 
			
		
	
		
			
				
					|  |  |  |  |                 let five = Poly::constant(5.into_fr()); | 
			
		
	
		
			
				
					|  |  |  |  |                 let wrong_poly = row_poly.clone() + x_pow_2 * five; | 
			
		
	
		
			
				
					|  |  |  |  |                 assert_ne!(wrong_poly.commitment(), row_commit); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -1057,8 +1170,7 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  |                     .iter() | 
			
		
	
		
			
				
					|  |  |  |  |                     .map(|&i| (i, bi_poly.evaluate(m, i))) | 
			
		
	
		
			
				
					|  |  |  |  |                     .collect(); | 
			
		
	
		
			
				
					|  |  |  |  |                 let my_row = | 
			
		
	
		
			
				
					|  |  |  |  |                     Poly::interpolate(received).expect("Failed to create `Poly` via interpolation"); | 
			
		
	
		
			
				
					|  |  |  |  |                 let my_row = Poly::interpolate(received); | 
			
		
	
		
			
				
					|  |  |  |  |                 assert_eq!(bi_poly.evaluate(m, 0), my_row.evaluate(0)); | 
			
		
	
		
			
				
					|  |  |  |  |                 assert_eq!(row_poly, my_row); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -1073,11 +1185,9 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  |         // The whole first column never gets added up in practice, because nobody has all the
 | 
			
		
	
		
			
				
					|  |  |  |  |         // information. We do it anyway here; entry `0` is the secret key that is not known to
 | 
			
		
	
		
			
				
					|  |  |  |  |         // anyone, neither a dealer, nor a node:
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut sec_key_set = Poly::zero().expect("Failed to create empty `Poly`"); | 
			
		
	
		
			
				
					|  |  |  |  |         let mut sec_key_set = Poly::zero(); | 
			
		
	
		
			
				
					|  |  |  |  |         for bi_poly in &bi_polys { | 
			
		
	
		
			
				
					|  |  |  |  |             sec_key_set += bi_poly | 
			
		
	
		
			
				
					|  |  |  |  |                 .row(0) | 
			
		
	
		
			
				
					|  |  |  |  |                 .expect("Failed to create `Poly` from row #0 for `BivarPoly`"); | 
			
		
	
		
			
				
					|  |  |  |  |             sec_key_set += bi_poly.row(0); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         for m in 1..=node_num { | 
			
		
	
		
			
				
					|  |  |  |  |             assert_eq!(sec_key_set.evaluate(m), sec_keys[m - 1]); | 
			
		
	
	
		
			
				
					|  |  |  | @ -1085,9 +1195,7 @@ mod tests { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // The sum of the first rows of the public commitments is the commitment to the secret key
 | 
			
		
	
		
			
				
					|  |  |  |  |         // set.
 | 
			
		
	
		
			
				
					|  |  |  |  |         let mut sum_commit = Poly::zero() | 
			
		
	
		
			
				
					|  |  |  |  |             .expect("Failed to create empty `Poly`") | 
			
		
	
		
			
				
					|  |  |  |  |             .commitment(); | 
			
		
	
		
			
				
					|  |  |  |  |         let mut sum_commit = Poly::zero().commitment(); | 
			
		
	
		
			
				
					|  |  |  |  |         for bi_commit in &pub_bi_commits { | 
			
		
	
		
			
				
					|  |  |  |  |             sum_commit += bi_commit.row(0); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |