Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce the need for extraneous generics in downstream code. #83

Draft
wants to merge 27 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
363 changes: 194 additions & 169 deletions src/fields/cubic_extension.rs

Large diffs are not rendered by default.

102 changes: 69 additions & 33 deletions src/fields/fp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use ark_relations::r1cs::{
use core::borrow::Borrow;

use crate::{
fields::{FieldOpsBounds, FieldVar},
fields::{FieldOpsBounds, FieldVar, FieldWithVar},
prelude::*,
Assignment, ToConstraintFieldGadget, Vec,
};
Expand Down Expand Up @@ -49,6 +49,20 @@ pub enum FpVar<F: PrimeField> {
Var(AllocatedFp<F>),
}

macro_rules! impl_field_ext {
($Fp:ident, $FpParams:ident) => {
impl<P: ark_ff::models::$FpParams> FieldWithVar for ark_ff::models::$Fp<P> {
type Var = FpVar<Self>;
}
};
}

impl_field_ext!(Fp256, Fp256Parameters);
impl_field_ext!(Fp320, Fp320Parameters);
impl_field_ext!(Fp384, Fp384Parameters);
impl_field_ext!(Fp768, Fp768Parameters);
impl_field_ext!(Fp832, Fp832Parameters);

impl<F: PrimeField> R1CSVar<F> for FpVar<F> {
type Value = F;

Expand Down Expand Up @@ -128,7 +142,7 @@ impl<F: PrimeField> AllocatedFp<F> {
/// Add many allocated Fp elements together.
///
/// This does not create any constraints and only creates one linear combination.
pub fn addmany<'a, I: Iterator<Item = &'a Self>>(iter: I) -> Self {
pub fn add_many<'a, I: Iterator<Item = &'a Self>>(iter: I) -> Self {
let mut cs = ConstraintSystemRef::None;
let mut has_value = true;
let mut value = F::zero();
Expand Down Expand Up @@ -686,27 +700,30 @@ impl<F: PrimeField> FieldVar<F, F> for FpVar<F> {
}

#[tracing::instrument(target = "r1cs")]
fn double(&self) -> Result<Self, SynthesisError> {
match self {
Self::Constant(c) => Ok(Self::Constant(c.double())),
Self::Var(v) => Ok(Self::Var(v.double()?)),
}
fn double_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
*self = match self {
Self::Constant(c) => Self::Constant(c.double()),
Self::Var(v) => Self::Var(v.double()?),
};
Ok(self)
}

#[tracing::instrument(target = "r1cs")]
fn negate(&self) -> Result<Self, SynthesisError> {
match self {
Self::Constant(c) => Ok(Self::Constant(-*c)),
Self::Var(v) => Ok(Self::Var(v.negate())),
}
fn negate_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
*self = match self {
Self::Constant(c) => Self::Constant(-*c),
Self::Var(v) => Self::Var(v.negate()),
};
Ok(self)
}

#[tracing::instrument(target = "r1cs")]
fn square(&self) -> Result<Self, SynthesisError> {
match self {
Self::Constant(c) => Ok(Self::Constant(c.square())),
Self::Var(v) => Ok(Self::Var(v.square()?)),
}
fn square_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
*self = match self {
Self::Constant(c) => Self::Constant(c.square()),
Self::Var(v) => Self::Var(v.square()?),
};
Ok(self)
}

/// Enforce that `self * other == result`.
Expand Down Expand Up @@ -781,15 +798,15 @@ impl_ops!(
add,
AddAssign,
add_assign,
|this: &'a FpVar<F>, other: &'a FpVar<F>| {
|this: &mut FpVar<F>, other: &'a FpVar<F>| {
use FpVar::*;
match (this, other) {
*this = match (&*this, other) {
(Constant(c1), Constant(c2)) => Constant(*c1 + *c2),
(Constant(c), Var(v)) | (Var(v), Constant(c)) => Var(v.add_constant(*c)),
(Var(v1), Var(v2)) => Var(v1.add(v2)),
}
};
},
|this: &'a FpVar<F>, other: F| { this + &FpVar::Constant(other) },
|this: &mut FpVar<F>, other: F| { *this = &*this + &FpVar::Constant(other) },
F: PrimeField,
);

Expand All @@ -800,16 +817,16 @@ impl_ops!(
sub,
SubAssign,
sub_assign,
|this: &'a FpVar<F>, other: &'a FpVar<F>| {
|this: &mut FpVar<F>, other: &'a FpVar<F>| {
use FpVar::*;
match (this, other) {
*this = match (&*this, other) {
(Constant(c1), Constant(c2)) => Constant(*c1 - *c2),
(Var(v), Constant(c)) => Var(v.sub_constant(*c)),
(Constant(c), Var(v)) => Var(v.sub_constant(*c).negate()),
(Var(v1), Var(v2)) => Var(v1.sub(v2)),
}
};
},
|this: &'a FpVar<F>, other: F| { this - &FpVar::Constant(other) },
|this: &mut FpVar<F>, other: F| { *this = &*this - &FpVar::Constant(other) },
F: PrimeField
);

Expand All @@ -820,20 +837,20 @@ impl_ops!(
mul,
MulAssign,
mul_assign,
|this: &'a FpVar<F>, other: &'a FpVar<F>| {
|this: &mut FpVar<F>, other: &'a FpVar<F>| {
use FpVar::*;
match (this, other) {
*this = match (&*this, other) {
(Constant(c1), Constant(c2)) => Constant(*c1 * *c2),
(Constant(c), Var(v)) | (Var(v), Constant(c)) => Var(v.mul_constant(*c)),
(Var(v1), Var(v2)) => Var(v1.mul(v2)),
}
};
},
|this: &'a FpVar<F>, other: F| {
if other.is_zero() {
|this: &mut FpVar<F>, other: F| {
*this = if other.is_zero() {
FpVar::zero()
} else {
this * &FpVar::Constant(other)
}
&*this * FpVar::Constant(other)
};
},
F: PrimeField
);
Expand Down Expand Up @@ -1045,7 +1062,7 @@ impl<F: PrimeField> AllocVar<F, F> for FpVar<F> {
impl<'a, F: PrimeField> Sum<&'a FpVar<F>> for FpVar<F> {
fn sum<I: Iterator<Item = &'a FpVar<F>>>(iter: I) -> FpVar<F> {
let mut sum_constants = F::zero();
let sum_variables = FpVar::Var(AllocatedFp::<F>::addmany(iter.filter_map(|x| match x {
let sum_variables = FpVar::Var(AllocatedFp::<F>::add_many(iter.filter_map(|x| match x {
FpVar::Constant(c) => {
sum_constants += c;
None
Expand All @@ -1058,6 +1075,25 @@ impl<'a, F: PrimeField> Sum<&'a FpVar<F>> for FpVar<F> {
}
}

impl<F: PrimeField> Sum<FpVar<F>> for FpVar<F> {
fn sum<I: Iterator<Item = FpVar<F>>>(iter: I) -> FpVar<F> {
let mut sum_constants = F::zero();
let vars = iter
.filter_map(|x| match x {
FpVar::Constant(c) => {
sum_constants += c;
None
}
FpVar::Var(v) => Some(v),
})
.collect::<Vec<_>>();
let sum_variables = FpVar::Var(AllocatedFp::<F>::add_many(vars.iter()));

let sum = sum_variables + sum_constants;
sum
}
}

#[cfg(test)]
mod test {
use crate::alloc::{AllocVar, AllocationMode};
Expand Down
16 changes: 12 additions & 4 deletions src/fields/fp12.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
use crate::fields::{fp2::Fp2Var, fp6_3over2::Fp6Var, quadratic_extension::*, FieldVar};
use crate::fields::{
fp2::Fp2Var, fp6_3over2::Fp6Var, quadratic_extension::*, FieldVar, FieldWithVar,
};
use ark_ff::fields::{fp12_2over3over2::*, fp6_3over2::Fp6Parameters, Field, QuadExtParameters};
use ark_relations::r1cs::SynthesisError;

/// A degree-12 extension field constructed as the tower of a
/// quadratic extension over a cubic extension over a quadratic extension field.
/// This is the R1CS equivalent of `ark_ff::fp12_2over3over2::Fp12<P>`.
pub type Fp12Var<P> = QuadExtVar<Fp6Var<<P as Fp12Parameters>::Fp6Params>, Fp12ParamsWrapper<P>>;
pub type Fp12Var<P> = QuadExtVar<Fp12ParamsWrapper<P>>;

type Fp2Params<P> = <<P as Fp12Parameters>::Fp6Params as Fp6Parameters>::Fp2Params;

impl<P: Fp12Parameters> QuadExtVarParams<Fp6Var<P::Fp6Params>> for Fp12ParamsWrapper<P> {
impl<P: Fp12Parameters> QuadExtVarParams for Fp12ParamsWrapper<P>
where
Self::BasePrimeField: FieldWithVar,
{
fn mul_base_field_var_by_frob_coeff(fe: &mut Fp6Var<P::Fp6Params>, power: usize) {
fe.c0 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
fe.c1 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
fe.c2 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
}
}

impl<P: Fp12Parameters> Fp12Var<P> {
impl<P: Fp12Parameters> Fp12Var<P>
where
<Fp12<P> as Field>::BasePrimeField: FieldWithVar,
{
/// Multiplies by a sparse element of the form `(c0 = (c0, c1, 0), c1 = (0,
/// d1, 0))`.
#[inline]
Expand Down
13 changes: 9 additions & 4 deletions src/fields/fp2.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use crate::fields::{fp::FpVar, quadratic_extension::*};
use crate::fields::{quadratic_extension::*, FieldWithVar};
use ark_ff::fields::{Fp2Parameters, Fp2ParamsWrapper, QuadExtParameters};

type FpVar<P> = <<Fp2ParamsWrapper<P> as QuadExtParameters>::BasePrimeField as FieldWithVar>::Var;

/// A quadratic extension field constructed over a prime field.
/// This is the R1CS equivalent of `ark_ff::Fp2<P>`.
pub type Fp2Var<P> = QuadExtVar<FpVar<<P as Fp2Parameters>::Fp>, Fp2ParamsWrapper<P>>;
pub type Fp2Var<P> = QuadExtVar<Fp2ParamsWrapper<P>>;

impl<P: Fp2Parameters> QuadExtVarParams<FpVar<P::Fp>> for Fp2ParamsWrapper<P> {
fn mul_base_field_var_by_frob_coeff(fe: &mut FpVar<P::Fp>, power: usize) {
impl<P: Fp2Parameters> QuadExtVarParams for Fp2ParamsWrapper<P>
where
Self::BaseField: FieldWithVar,
{
fn mul_base_field_var_by_frob_coeff(fe: &mut FpVar<P>, power: usize) {
*fe *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
}
}
17 changes: 9 additions & 8 deletions src/fields/fp3.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use crate::fields::{cubic_extension::*, fp::FpVar};
use crate::fields::{cubic_extension::*, FieldWithVar};
use ark_ff::fields::{CubicExtParameters, Fp3Parameters, Fp3ParamsWrapper};

type FpVar<P> = <<Fp3ParamsWrapper<P> as CubicExtParameters>::BasePrimeField as FieldWithVar>::Var;

/// A cubic extension field constructed over a prime field.
/// This is the R1CS equivalent of `ark_ff::Fp3<P>`.
pub type Fp3Var<P> = CubicExtVar<FpVar<<P as Fp3Parameters>::Fp>, Fp3ParamsWrapper<P>>;
pub type Fp3Var<P> = CubicExtVar<Fp3ParamsWrapper<P>>;

impl<P: Fp3Parameters> CubicExtVarParams<FpVar<P::Fp>> for Fp3ParamsWrapper<P> {
fn mul_base_field_vars_by_frob_coeff(
c1: &mut FpVar<P::Fp>,
c2: &mut FpVar<P::Fp>,
power: usize,
) {
impl<P: Fp3Parameters> CubicExtVarParams for Fp3ParamsWrapper<P>
where
Self::BasePrimeField: FieldWithVar,
{
fn mul_base_field_vars_by_frob_coeff(c1: &mut FpVar<P>, c2: &mut FpVar<P>, power: usize) {
*c1 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
*c2 *= Self::FROBENIUS_COEFF_C2[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
}
Expand Down
9 changes: 6 additions & 3 deletions src/fields/fp4.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::fields::{fp2::Fp2Var, quadratic_extension::*};
use crate::fields::{fp2::Fp2Var, quadratic_extension::*, FieldWithVar};
use ark_ff::fields::{Fp4Parameters, Fp4ParamsWrapper, QuadExtParameters};

/// A quartic extension field constructed as the tower of a
/// quadratic extension over a quadratic extension field.
/// This is the R1CS equivalent of `ark_ff::Fp4<P>`.
pub type Fp4Var<P> = QuadExtVar<Fp2Var<<P as Fp4Parameters>::Fp2Params>, Fp4ParamsWrapper<P>>;
pub type Fp4Var<P> = QuadExtVar<Fp4ParamsWrapper<P>>;

impl<P: Fp4Parameters> QuadExtVarParams<Fp2Var<P::Fp2Params>> for Fp4ParamsWrapper<P> {
impl<P: Fp4Parameters> QuadExtVarParams for Fp4ParamsWrapper<P>
where
Self::BasePrimeField: FieldWithVar,
{
fn mul_base_field_var_by_frob_coeff(fe: &mut Fp2Var<P::Fp2Params>, power: usize) {
fe.c0 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
fe.c1 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
Expand Down
9 changes: 6 additions & 3 deletions src/fields/fp6_2over3.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use crate::fields::{fp3::Fp3Var, quadratic_extension::*};
use crate::fields::{fp3::Fp3Var, quadratic_extension::*, FieldWithVar};
use ark_ff::fields::{fp6_2over3::*, QuadExtParameters};

/// A sextic extension field constructed as the tower of a
/// quadratic extension over a cubic extension field.
/// This is the R1CS equivalent of `ark_ff::fp6_2over3::Fp6<P>`.
pub type Fp6Var<P> = QuadExtVar<Fp3Var<<P as Fp6Parameters>::Fp3Params>, Fp6ParamsWrapper<P>>;
pub type Fp6Var<P> = QuadExtVar<Fp6ParamsWrapper<P>>;

impl<P: Fp6Parameters> QuadExtVarParams<Fp3Var<P::Fp3Params>> for Fp6ParamsWrapper<P> {
impl<P: Fp6Parameters> QuadExtVarParams for Fp6ParamsWrapper<P>
where
Self::BasePrimeField: FieldWithVar,
{
fn mul_base_field_var_by_frob_coeff(fe: &mut Fp3Var<P::Fp3Params>, power: usize) {
fe.c0 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
fe.c1 *= Self::FROBENIUS_COEFF_C1[power % Self::DEGREE_OVER_BASE_PRIME_FIELD];
Expand Down
21 changes: 16 additions & 5 deletions src/fields/fp6_3over2.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
use crate::fields::{cubic_extension::*, fp2::*};
use crate::fields::{cubic_extension::*, fp2::*, FieldWithVar};
use ark_ff::fields::{fp6_3over2::*, CubicExtParameters, Fp2};
use ark_relations::r1cs::SynthesisError;
use core::ops::MulAssign;

/// A sextic extension field constructed as the tower of a
/// cubic extension over a quadratic extension field.
/// This is the R1CS equivalent of `ark_ff::fp6_3over3::Fp6<P>`.
pub type Fp6Var<P> = CubicExtVar<Fp2Var<<P as Fp6Parameters>::Fp2Params>, Fp6ParamsWrapper<P>>;
pub type Fp6Var<P> = CubicExtVar<Fp6ParamsWrapper<P>>;

impl<P: Fp6Parameters> CubicExtVarParams<Fp2Var<P::Fp2Params>> for Fp6ParamsWrapper<P> {
type Fp<P> = <Fp6ParamsWrapper<P> as CubicExtParameters>::BasePrimeField;

impl<P: Fp6Parameters> CubicExtVarParams for Fp6ParamsWrapper<P>
where
Fp<P>: FieldWithVar,
{
fn mul_base_field_vars_by_frob_coeff(
c1: &mut Fp2Var<P::Fp2Params>,
c2: &mut Fp2Var<P::Fp2Params>,
Expand All @@ -19,7 +24,10 @@ impl<P: Fp6Parameters> CubicExtVarParams<Fp2Var<P::Fp2Params>> for Fp6ParamsWrap
}
}

impl<P: Fp6Parameters> Fp6Var<P> {
impl<P: Fp6Parameters> Fp6Var<P>
where
Fp<P>: FieldWithVar,
{
/// Multiplies `self` by a sparse element which has `c0 == c2 == zero`.
pub fn mul_by_0_c1_0(&self, c1: &Fp2Var<P::Fp2Params>) -> Result<Self, SynthesisError> {
// Karatsuba multiplication
Expand Down Expand Up @@ -76,7 +84,10 @@ impl<P: Fp6Parameters> Fp6Var<P> {
}
}

impl<P: Fp6Parameters> MulAssign<Fp2<P::Fp2Params>> for Fp6Var<P> {
impl<P: Fp6Parameters> MulAssign<Fp2<P::Fp2Params>> for Fp6Var<P>
where
Fp<P>: FieldWithVar,
{
fn mul_assign(&mut self, other: Fp2<P::Fp2Params>) {
self.c0 *= other;
self.c1 *= other;
Expand Down
Loading