Skip to content

Commit

Permalink
algebra: authenticated-poly: Implement scalar multiplication
Browse files Browse the repository at this point in the history
  • Loading branch information
joeykraut committed Oct 13, 2023
1 parent 27af455 commit 3835d29
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 10 deletions.
116 changes: 106 additions & 10 deletions src/algebra/poly/authenticated_poly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,41 @@ impl<C: CurveGroup> Mul<&AuthenticatedDensePoly<C>> for &AuthenticatedDensePoly<
}
}

// --- Scalar Multiplication --- //

impl<C: CurveGroup> Mul<&Scalar<C>> for &AuthenticatedDensePoly<C> {
type Output = AuthenticatedDensePoly<C>;

fn mul(self, rhs: &Scalar<C>) -> Self::Output {
let new_coeffs = self.coeffs.iter().map(|coeff| coeff * rhs).collect_vec();
AuthenticatedDensePoly::from_coeffs(new_coeffs)
}
}
impl_borrow_variants!(AuthenticatedDensePoly<C>, Mul, mul, *, Scalar<C>, C: CurveGroup);
impl_commutative!(AuthenticatedDensePoly<C>, Mul, mul, *, Scalar<C>, C: CurveGroup);

impl<C: CurveGroup> Mul<&ScalarResult<C>> for &AuthenticatedDensePoly<C> {
type Output = AuthenticatedDensePoly<C>;

fn mul(self, rhs: &ScalarResult<C>) -> Self::Output {
let new_coeffs = self.coeffs.iter().map(|coeff| coeff * rhs).collect_vec();
AuthenticatedDensePoly::from_coeffs(new_coeffs)
}
}
impl_borrow_variants!(AuthenticatedDensePoly<C>, Mul, mul, *, ScalarResult<C>, C: CurveGroup);
impl_commutative!(AuthenticatedDensePoly<C>, Mul, mul, *, ScalarResult<C>, C: CurveGroup);

impl<C: CurveGroup> Mul<&AuthenticatedScalarResult<C>> for &AuthenticatedDensePoly<C> {
type Output = AuthenticatedDensePoly<C>;

fn mul(self, rhs: &AuthenticatedScalarResult<C>) -> Self::Output {
let new_coeffs = self.coeffs.iter().map(|coeff| coeff * rhs).collect_vec();
AuthenticatedDensePoly::from_coeffs(new_coeffs)
}
}
impl_borrow_variants!(AuthenticatedDensePoly<C>, Mul, mul, *, AuthenticatedScalarResult<C>, C: CurveGroup);
impl_commutative!(AuthenticatedDensePoly<C>, Mul, mul, *, AuthenticatedScalarResult<C>, C: CurveGroup);

// --- Division --- //
/// Given a public divisor b(x) and shared dividend a(x) = a_1(x) + a_2(x) for party shares a_1, a_2
/// We can divide each share locally to obtain a secret sharing of \floor{a(x) / b(x)}
Expand Down Expand Up @@ -318,7 +353,7 @@ impl<C: CurveGroup> Div<&DensePolynomialResult<C>> for &AuthenticatedDensePoly<C
}

let mut remainder = self.clone();
let mut quotient_coeffs = fabric.ones_authenticated(quotient_degree + 1);
let mut quotient_coeffs = fabric.zeros_authenticated(quotient_degree + 1);

let divisor_leading_inverse = rhs.coeffs.last().unwrap().inverse();
for deg in (0..=quotient_degree).rev() {
Expand All @@ -339,9 +374,6 @@ impl<C: CurveGroup> Div<&DensePolynomialResult<C>> for &AuthenticatedDensePoly<C
remainder.coeffs.pop();
}

// Reverse the quotient coefficients, long division generates them leading coefficient first, and
// we store them leading coefficient last
// quotient_coeffs.reverse();
AuthenticatedDensePoly::from_coeffs(quotient_coeffs)
}
}
Expand Down Expand Up @@ -541,18 +573,82 @@ mod test {
assert_eq!(res.unwrap(), expected_res);
}

/// Tests multiplying by a public constant scalar
#[tokio::test]
async fn test_scalar_mul_constant() {
let mut rng = thread_rng();
let poly = random_poly(DEGREE_BOUND);
let scaling_factor = Scalar::random(&mut rng);

let expected_res = &poly * scaling_factor.inner();

let (res, _) = execute_mock_mpc(|fabric| {
let poly = poly.clone();
async move {
let shared_poly = share_poly(poly, PARTY0, &fabric);
(shared_poly * scaling_factor).open_authenticated().await
}
})
.await;

assert!(res.is_ok());
assert_eq!(res.unwrap(), expected_res);
}

/// Tests multiplying by a public result
#[tokio::test]
async fn test_scalar_mul_public() {
let mut rng = thread_rng();
let poly = random_poly(DEGREE_BOUND);
let scaling_factor = Scalar::random(&mut rng);

let expected_res = &poly * scaling_factor.inner();

let (res, _) = execute_mock_mpc(|fabric| {
let poly = poly.clone();
async move {
let shared_poly = share_poly(poly, PARTY0, &fabric);
let scaling_factor = fabric.allocate_scalar(scaling_factor);

(shared_poly * scaling_factor).open_authenticated().await
}
})
.await;

assert!(res.is_ok());
assert_eq!(res.unwrap(), expected_res);
}

/// Tests multiplying by a shared scalar
#[tokio::test]
async fn test_scalar_mul() {
let mut rng = thread_rng();
let poly = random_poly(DEGREE_BOUND);
let scaling_factor = Scalar::random(&mut rng);

let expected_res = &poly * scaling_factor.inner();

let (res, _) = execute_mock_mpc(|fabric| {
let poly = poly.clone();
async move {
let shared_poly = share_poly(poly, PARTY0, &fabric);
let scaling_factor = fabric.share_scalar(scaling_factor, PARTY0);

(shared_poly * scaling_factor).open_authenticated().await
}
})
.await;

assert!(res.is_ok());
assert_eq!(res.unwrap(), expected_res);
}

/// Tests dividing a shared polynomial by a public polynomial
#[tokio::test]
async fn test_div_polynomial_public() {
let poly1 = random_poly(DEGREE_BOUND);
let poly2 = random_poly(DEGREE_BOUND);

let (poly1, poly2) = if poly1.degree() < poly2.degree() {
(poly2, poly1)
} else {
(poly1, poly2)
};

let expected_res = &poly1 / &poly2;

let (res, _) = execute_mock_mpc(|fabric| {
Expand Down
1 change: 1 addition & 0 deletions src/algebra/poly/poly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ impl<C: CurveGroup> Mul<&DensePolynomialResult<C>> for &DensePolynomialResult<C>
impl_borrow_variants!(DensePolynomialResult<C>, Mul, mul, *, DensePolynomialResult<C>, C: CurveGroup);

// --- Scalar Multiplication --- //

impl<C: CurveGroup> Mul<&Scalar<C>> for &DensePolynomialResult<C> {
type Output = DensePolynomialResult<C>;

Expand Down

0 comments on commit 3835d29

Please sign in to comment.