Skip to content

Commit

Permalink
Merge branch 'refactor/move_circom_witness_ext' of github.com:TaceoLa…
Browse files Browse the repository at this point in the history
…bs/collaborative-circom into refactor/move_circom_witness_ext
  • Loading branch information
0xThemis committed Sep 13, 2024
2 parents 180b751 + 6a6b67b commit 2a084a2
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 49 deletions.
2 changes: 1 addition & 1 deletion co-circom/co-plonk/src/mpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub trait CircomPlonkProver<P: Pairing> {
) -> Self::PointShareG1;

fn evaluate_poly_public(
poly: &[Self::ArithmeticShare],
poly: Vec<Self::ArithmeticShare>,
point: P::ScalarField,
) -> Self::ArithmeticShare;
}
6 changes: 2 additions & 4 deletions co-circom/co-plonk/src/mpc/plain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,10 @@ impl<P: Pairing> CircomPlonkProver<P> for PlainPlonkDriver {
}

fn evaluate_poly_public(
coeffs: &[Self::ArithmeticShare],
coeffs: Vec<Self::ArithmeticShare>,
point: P::ScalarField,
) -> Self::ArithmeticShare {
let poly = DensePolynomial {
coeffs: coeffs.to_vec(),
};
let poly = DensePolynomial { coeffs };
poly.evaluate(&point)
}
}
2 changes: 1 addition & 1 deletion co-circom/co-plonk/src/mpc/rep3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl<P: Pairing, N: Rep3Network> CircomPlonkProver<P> for Rep3PlonkDriver<N> {
}

fn evaluate_poly_public(
coeffs: &[Self::ArithmeticShare],
coeffs: Vec<Self::ArithmeticShare>,
point: P::ScalarField,
) -> Self::ArithmeticShare {
poly::eval_poly(coeffs, point)
Expand Down
26 changes: 13 additions & 13 deletions co-circom/co-plonk/src/mpc/shamir.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use ark_ec::pairing::Pairing;
use ark_ff::PrimeField;
use ark_poly::univariate::DensePolynomial;
use ark_poly::EvaluationDomain;
use ark_poly::Polynomial;

use mpc_core::protocols::shamir::{
arithmetic, network::ShamirNetwork, pointshare, ShamirPointShare, ShamirPrimeFieldShare,
Expand Down Expand Up @@ -94,35 +96,31 @@ impl<P: Pairing, N: ShamirNetwork> CircomPlonkProver<P> for ShamirPlonkDriver<P:
b: &[Self::ArithmeticShare],
c: &[Self::ArithmeticShare],
) -> IoResult<Vec<Self::ArithmeticShare>> {
todo!();
//let mut result = arithmetic::mul_vec(b, c, &mut self.protocol).await?;
//arithmetic::add_vec_assign(&mut result, a);
//Ok(result)
let mut result = arithmetic::mul_vec(b, c, &mut self.protocol).await?;
arithmetic::add_vec_assign(&mut result, a);
Ok(result)
}

async fn mul_open_vec(
&mut self,
a: &[Self::ArithmeticShare],
b: &[Self::ArithmeticShare],
) -> IoResult<Vec<<P as Pairing>::ScalarField>> {
todo!();
//arithmetic::mul_open_vec(a, b, &mut self.protocol).await
arithmetic::mul_open_vec(a, b, &mut self.protocol).await
}

async fn open_vec(
&mut self,
a: &[Self::ArithmeticShare],
) -> IoResult<Vec<<P as Pairing>::ScalarField>> {
todo!();
//arithmetic::open_vec(a, &mut self.protocol).await
arithmetic::open_vec(a, &mut self.protocol).await
}

async fn inv_vec(
&mut self,
a: &[Self::ArithmeticShare],
) -> IoResult<Vec<Self::ArithmeticShare>> {
todo!()
//arithmetic::inv_vec(a, &mut self.protocol).await
arithmetic::inv_vec(a, &mut self.protocol).await
}

fn promote_to_trivial_share(
Expand Down Expand Up @@ -165,10 +163,12 @@ impl<P: Pairing, N: ShamirNetwork> CircomPlonkProver<P> for ShamirPlonkDriver<P:
}

fn evaluate_poly_public(
poly: &[Self::ArithmeticShare],
poly: Vec<Self::ArithmeticShare>,
point: <P as Pairing>::ScalarField,
) -> Self::ArithmeticShare {
// poly::eval_poly(coeffs, point)
todo!() // TODO RH create poly module
let poly = DensePolynomial {
coeffs: Self::ArithmeticShare::convert_vec(poly),
};
Self::ArithmeticShare::new(poly.evaluate(&point))
}
}
8 changes: 4 additions & 4 deletions co-circom/co-plonk/src/round4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ impl<'a, P: Pairing, T: CircomPlonkProver<P>> Round4<'a, P, T> {
let challenges = Round4Challenges::new(challenges, xi);
tracing::debug!("xi: {xi}");
tracing::debug!("evaluating poly a");
let eval_a = T::evaluate_poly_public(&polys.a.poly, challenges.xi);
let eval_a = T::evaluate_poly_public(polys.a.poly, challenges.xi);
tracing::debug!("evaluating poly b");
let eval_b = T::evaluate_poly_public(&polys.b.poly, challenges.xi);
let eval_b = T::evaluate_poly_public(polys.b.poly, challenges.xi);
tracing::debug!("evaluating poly c");
let eval_c = T::evaluate_poly_public(&polys.c.poly, challenges.xi);
let eval_c = T::evaluate_poly_public(polys.c.poly, challenges.xi);
tracing::debug!("evaluating poly z");
let eval_z = T::evaluate_poly_public(&polys.z.poly, xiw);
let eval_z = T::evaluate_poly_public(polys.z.poly, xiw);

let opened = runtime.block_on(driver.open_vec(&[eval_a, eval_b, eval_c, eval_z]))?;

Expand Down
4 changes: 3 additions & 1 deletion mpc-core/src/protocols/rep3/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ pub async fn inv<F: PrimeField, N: Rep3Network>(
Ok(r * y_inv)
}

/// Computes the inverse of a vector of shared field elements
pub async fn inv_vec<F: PrimeField, N: Rep3Network>(
a: &[FieldShare<F>],
io_context: &mut IoContext<N>,
Expand Down Expand Up @@ -220,7 +221,7 @@ pub async fn open_vec<F: PrimeField, N: Rep3Network>(
// because we use it exactly once in PLONK where we do it for 4
// shares..
let (a, b) = a
.into_iter()
.iter()
.map(|share| (share.a, share.b))
.collect::<(Vec<F>, Vec<F>)>();
let c = io_context.network.reshare_many(&b).await?;
Expand Down Expand Up @@ -276,6 +277,7 @@ pub async fn mul_open<F: PrimeField, N: Rep3Network>(
Ok(a + b + c)
}

/// This function performs a multiplication directly followed by an opening. This safes one round of communication in some MPC protocols compared to calling `mul` and `open` separately.
pub async fn mul_open_vec<F: PrimeField, N: Rep3Network>(
a: &[FieldShare<F>],
b: &[FieldShare<F>],
Expand Down
6 changes: 3 additions & 3 deletions mpc-core/src/protocols/rep3/poly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn horner_evaluate<F: PrimeField>(poly_coeffs: &[FieldShare<F>], point: F) -> Fi

// This is copied from
// https://docs.rs/ark-poly/latest/src/ark_poly/polynomial/univariate/dense.rs.html#56
pub fn eval_poly<F: PrimeField>(coeffs: &[FieldShare<F>], point: F) -> FieldShare<F> {
pub fn eval_poly<F: PrimeField>(coeffs: Vec<FieldShare<F>>, point: F) -> FieldShare<F> {
// Horners method - parallel method
// compute the number of threads we will be using.
// TODO investigate how this behaves if we are in a rayon scope. Does this return all
Expand All @@ -53,8 +53,8 @@ pub fn eval_poly<F: PrimeField>(coeffs: &[FieldShare<F>], point: F) -> FieldShar
.par_chunks(num_elem_per_thread)
.enumerate()
.map(|(i, chunk)| {
let mut thread_result = horner_evaluate(&chunk, point);
let power = point.pow(&[(i * num_elem_per_thread) as u64]);
let mut thread_result = horner_evaluate(chunk, point);
let power = point.pow([(i * num_elem_per_thread) as u64]);
thread_result.a *= power;
thread_result.b *= power;
thread_result
Expand Down
47 changes: 28 additions & 19 deletions mpc-core/src/protocols/shamir/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use ark_ff::PrimeField;
use itertools::{izip, Itertools};

use super::{core, network::ShamirNetwork, IoResult, ShamirProtocol};

Expand Down Expand Up @@ -37,6 +38,13 @@ pub fn add_assign_public<F: PrimeField>(shared: &mut ShamirShare<F>, public: F)
*shared += public;
}

/// Performs element-wise addition of two slices of shares and stores the result in `lhs`.
pub fn add_vec_assign<F: PrimeField>(lhs: &mut [ShamirShare<F>], rhs: &[ShamirShare<F>]) {
for (a, b) in izip!(lhs.iter_mut(), rhs.iter()) {
*a += b;
}
}

/// Performs multiplication between two shares.
pub async fn mul<F: PrimeField, N: ShamirNetwork>(
a: ShamirShare<F>,
Expand Down Expand Up @@ -89,24 +97,27 @@ pub async fn inv<F: PrimeField, N: ShamirNetwork>(
}

/// Computes the inverse of a vector of shared field elements
pub async fn inv_many<F: PrimeField, N: ShamirNetwork>(
pub async fn inv_vec<F: PrimeField, N: ShamirNetwork>(
a: &[ShamirShare<F>],
shamir: &mut ShamirProtocol<F, N>,
) -> std::io::Result<Vec<ShamirShare<F>>> {
todo!()
//let r = (0..a.len())
// .map(|_| shamir.rand().await)
// .collect::<Result<Vec<_>, _>>()?;
//let y = self.mul_open_many(a, &r)?;
//if y.iter().any(|y| y.is_zero()) {
// return Err(std::io::Error::new(
// std::io::ErrorKind::InvalidData,
// "During execution of inverse in MPC: cannot compute inverse of zero",
// ));
//}

//let res = izip!(r, y).map(|(r, y)| r * y.inverse().unwrap()).collect();
//Ok(res)
let r = (0..a.len())
//.map(|_| shamir.rand().await?) // TODO: cannot use async here but rand will soon be sync again
.map(|_| {
futures::executor::block_on(shamir.rand())
.expect("the soon to be implemented random variant will not return an IoResult")
})
.collect_vec();
let y = mul_open_vec(a, &r, shamir).await?;
if y.iter().any(|y| y.is_zero()) {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"During execution of inverse in MPC: cannot compute inverse of zero",
));
}

// we can unwrap as we checked that none of the y is zero
Ok(izip!(r, y).map(|(r, y)| r * y.inverse().unwrap()).collect())
}

/// Performs negation of a share
Expand All @@ -128,7 +139,7 @@ pub async fn open<F: PrimeField, N: ShamirNetwork>(
}

/// Opens a vector of shared values and returns the corresponding field elements.
pub async fn open_many<F: PrimeField, N: ShamirNetwork>(
pub async fn open_vec<F: PrimeField, N: ShamirNetwork>(
a: &[ShamirShare<F>],
shamir: &mut ShamirProtocol<F, N>,
) -> IoResult<Vec<F>> {
Expand Down Expand Up @@ -176,8 +187,6 @@ pub fn promote_to_trivial_shares<F: PrimeField>(public_values: &[F]) -> Vec<Sham
.collect()
}



/*
fn clone_from_slice(
&self,
Expand Down Expand Up @@ -209,7 +218,7 @@ async fn mul_open<F: PrimeField, N: ShamirNetwork>(
}

/// This function performs a multiplication directly followed by an opening. This is preferred over Open(Mul(\[x\], \[y\])), since Mul performs resharing of the result for degree reduction. Thus, mul_open(\[x\], \[y\]) requires less communication in fewer rounds compared to Open(Mul(\[x\], \[y\])).
pub async fn mul_open_many<F: PrimeField, N: ShamirNetwork>(
pub async fn mul_open_vec<F: PrimeField, N: ShamirNetwork>(
a: &[ShamirShare<F>],
b: &[ShamirShare<F>],
shamir: &mut ShamirProtocol<F, N>,
Expand Down
10 changes: 7 additions & 3 deletions mpc-core/src/protocols/shamir/arithmetic/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ impl<F: PrimeField> std::ops::AddAssign for ShamirPrimeFieldShare<F> {
}
}

impl<F: PrimeField> std::ops::AddAssign<&ShamirPrimeFieldShare<F>> for ShamirPrimeFieldShare<F> {
fn add_assign(&mut self, rhs: &Self) {
self.a += rhs.a;
}
}

impl<F: PrimeField> std::ops::Add<&ShamirPrimeFieldShare<F>> for ShamirPrimeFieldShare<F> {
type Output = Self;

Expand Down Expand Up @@ -150,9 +156,7 @@ impl<F: PrimeField> std::ops::Neg for &ShamirPrimeFieldShare<F> {

impl<F: PrimeField> ark_ff::Zero for ShamirPrimeFieldShare<F> {
fn zero() -> Self {
Self {
a: F::zero(),
}
Self { a: F::zero() }
}

fn is_zero(&self) -> bool {
Expand Down

0 comments on commit 2a084a2

Please sign in to comment.