mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-07 14:31:32 +01:00
Add Mul<NonNativeFieldVar> for Group (#134)
This commit is contained in:
29
.github/workflows/ci.yml
vendored
29
.github/workflows/ci.yml
vendored
@@ -109,14 +109,14 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Rust (${{ matrix.rust }})
|
||||
- name: Install Rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
id: toolchain-thumbv6m
|
||||
with:
|
||||
target: thumbv6m-none-eabi
|
||||
- run: rustup override set ${{steps.toolchain-thumbv6m.outputs.name}}
|
||||
|
||||
- name: Install Rust ARM64 (${{ matrix.rust }})
|
||||
- name: Install Rust ARM64
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
id: toolchain-aarch64
|
||||
with:
|
||||
@@ -152,12 +152,12 @@ jobs:
|
||||
- ed_on_bls12_381
|
||||
steps:
|
||||
- name: Checkout curves
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: arkworks-rs/curves
|
||||
repository: arkworks-rs/algebra
|
||||
|
||||
- name: Checkout r1cs-std
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: r1cs-std
|
||||
|
||||
@@ -166,6 +166,7 @@ jobs:
|
||||
|
||||
- name: Patch cargo.toml
|
||||
run: |
|
||||
cd curves
|
||||
if grep -q "\[patch.crates-io\]" Cargo.toml ; then
|
||||
MATCH=$(awk '/\[patch.crates-io\]/{ print NR; exit }' Cargo.toml);
|
||||
sed -i "$MATCH,\$d" Cargo.toml
|
||||
@@ -173,15 +174,13 @@ jobs:
|
||||
{
|
||||
echo "[patch.crates-io]"
|
||||
echo "ark-std = { git = 'https://github.com/arkworks-rs/std' }"
|
||||
echo "ark-ec = { git = 'https://github.com/arkworks-rs/algebra' }"
|
||||
echo "ark-ff = { git = 'https://github.com/arkworks-rs/algebra' }"
|
||||
echo "ark-poly = { git = 'https://github.com/arkworks-rs/algebra' }"
|
||||
echo "ark-ec = { path = '../ec' }"
|
||||
echo "ark-ff = { path = '../ff' }"
|
||||
echo "ark-poly = { path = '../poly' }"
|
||||
echo "ark-relations = { git = 'https://github.com/arkworks-rs/snark' }"
|
||||
echo "ark-serialize = { git = 'https://github.com/arkworks-rs/algebra' }"
|
||||
echo "ark-algebra-bench-templates = { git = 'https://github.com/arkworks-rs/algebra' }"
|
||||
echo "ark-algebra-test-templates = { git = 'https://github.com/arkworks-rs/algebra' }"
|
||||
echo "ark-r1cs-std = { path = 'r1cs-std' }"
|
||||
echo "ark-serialize = { path = '../serialize' }"
|
||||
echo "ark-algebra-bench-templates = { path = '../bench-templates' }"
|
||||
echo "ark-algebra-test-templates = { path = '../test-templates' }"
|
||||
echo "ark-r1cs-std = { path = '../r1cs-std' }"
|
||||
} >> Cargo.toml
|
||||
|
||||
- name: Test on ${{ matrix.curve }}
|
||||
run: "cd ${{ matrix.curve }} && cargo test --features 'r1cs'"
|
||||
cd ${{ matrix.curve }} && cargo test --features 'r1cs'
|
||||
@@ -342,7 +342,7 @@ impl<ConstraintF: Field> AllocVar<u8, ConstraintF> for UInt8<ConstraintF> {
|
||||
/// `ConstraintF::MODULUS_BIT_SIZE - 1` chunks and converts each chunk, which is
|
||||
/// assumed to be little-endian, to its `FpVar<ConstraintF>` representation.
|
||||
/// This is the gadget counterpart to the `[u8]` implementation of
|
||||
/// [ToConstraintField](ark_ff::ToConstraintField).
|
||||
/// [`ToConstraintField`].
|
||||
impl<ConstraintF: PrimeField> ToConstraintFieldGadget<ConstraintF> for [UInt8<ConstraintF>] {
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_constraint_field(&self) -> Result<Vec<FpVar<ConstraintF>>, SynthesisError> {
|
||||
|
||||
@@ -57,14 +57,13 @@ impl<TargetField: PrimeField, BaseField: PrimeField>
|
||||
optimization_type,
|
||||
);
|
||||
|
||||
let mut base_repr: <TargetField as PrimeField>::BigInt = TargetField::one().into_bigint();
|
||||
|
||||
// Convert 2^{(params.bits_per_limb - 1)} into the TargetField and then double
|
||||
// the base This is because 2^{(params.bits_per_limb)} might indeed be
|
||||
// larger than the target field's prime.
|
||||
base_repr.muln((params.bits_per_limb - 1) as u32);
|
||||
let mut base: TargetField = TargetField::from_bigint(base_repr).unwrap();
|
||||
base = base + &base;
|
||||
let base_repr = TargetField::ONE.into_bigint() << (params.bits_per_limb - 1) as u32;
|
||||
|
||||
let mut base = TargetField::from_bigint(base_repr).unwrap();
|
||||
base.double_in_place();
|
||||
|
||||
let mut result = TargetField::zero();
|
||||
let mut power = TargetField::one();
|
||||
@@ -206,25 +205,21 @@ impl<TargetField: PrimeField, BaseField: PrimeField>
|
||||
> BaseField::MODULUS_BIT_SIZE as usize - 1)
|
||||
{
|
||||
Reducer::reduce(&mut other)?;
|
||||
surfeit = overhead!(other.num_of_additions_over_normal_form + BaseField::one()) + 1;
|
||||
surfeit = overhead!(other.num_of_additions_over_normal_form + BaseField::ONE) + 1;
|
||||
}
|
||||
|
||||
// Step 2: construct the padding
|
||||
let mut pad_non_top_limb_repr: <BaseField as PrimeField>::BigInt =
|
||||
BaseField::one().into_bigint();
|
||||
let mut pad_top_limb_repr: <BaseField as PrimeField>::BigInt = pad_non_top_limb_repr;
|
||||
let mut pad_non_top_limb = BaseField::ONE.into_bigint();
|
||||
let mut pad_top_limb = pad_non_top_limb;
|
||||
|
||||
pad_non_top_limb_repr.muln((surfeit + params.bits_per_limb) as u32);
|
||||
let pad_non_top_limb = BaseField::from_bigint(pad_non_top_limb_repr).unwrap();
|
||||
pad_non_top_limb <<= (surfeit + params.bits_per_limb) as u32;
|
||||
let pad_non_top_limb = BaseField::from_bigint(pad_non_top_limb).unwrap();
|
||||
|
||||
pad_top_limb_repr.muln(
|
||||
(surfeit
|
||||
+ (TargetField::MODULUS_BIT_SIZE as usize
|
||||
- params.bits_per_limb * (params.num_limbs - 1))) as u32,
|
||||
);
|
||||
let pad_top_limb = BaseField::from_bigint(pad_top_limb_repr).unwrap();
|
||||
pad_top_limb <<= (surfeit + TargetField::MODULUS_BIT_SIZE as usize
|
||||
- params.bits_per_limb * (params.num_limbs - 1)) as u32;
|
||||
let pad_top_limb = BaseField::from_bigint(pad_top_limb).unwrap();
|
||||
|
||||
let mut pad_limbs = Vec::new();
|
||||
let mut pad_limbs = Vec::with_capacity(self.limbs.len());
|
||||
pad_limbs.push(pad_top_limb);
|
||||
for _ in 0..self.limbs.len() - 1 {
|
||||
pad_limbs.push(pad_non_top_limb);
|
||||
@@ -236,12 +231,12 @@ impl<TargetField: PrimeField, BaseField: PrimeField>
|
||||
Self::get_limbs_representations(&pad_to_kp_gap, self.get_optimization_type())?;
|
||||
|
||||
// Step 4: the result is self + pad + pad_to_kp - other
|
||||
let mut limbs = Vec::new();
|
||||
let mut limbs = Vec::with_capacity(self.limbs.len());
|
||||
for (i, ((this_limb, other_limb), pad_to_kp_limb)) in self
|
||||
.limbs
|
||||
.iter()
|
||||
.zip(other.limbs.iter())
|
||||
.zip(pad_to_kp_limbs.iter())
|
||||
.zip(&other.limbs)
|
||||
.zip(&pad_to_kp_limbs)
|
||||
.enumerate()
|
||||
{
|
||||
if i != 0 {
|
||||
@@ -341,7 +336,7 @@ impl<TargetField: PrimeField, BaseField: PrimeField>
|
||||
&cur_bits[cur_bits.len() - params.bits_per_limb..],
|
||||
); // therefore, the lowest `bits_per_non_top_limb` bits is what we want.
|
||||
limbs.push(BaseField::from_bigint(cur_mod_r).unwrap());
|
||||
cur.divn(params.bits_per_limb as u32);
|
||||
cur >>= params.bits_per_limb as u32;
|
||||
}
|
||||
|
||||
// then we reserve, so that the limbs are ``big limb first''
|
||||
|
||||
@@ -240,7 +240,7 @@ impl<TargetField: PrimeField, BaseField: PrimeField> Reducer<TargetField, BaseFi
|
||||
let mut cur = BaseField::one().into_bigint();
|
||||
for _ in 0..num_limb_in_a_group {
|
||||
array.push(BaseField::from_bigint(cur).unwrap());
|
||||
cur.muln(shift_per_limb as u32);
|
||||
cur <<= shift_per_limb as u32;
|
||||
}
|
||||
|
||||
array
|
||||
@@ -280,16 +280,13 @@ impl<TargetField: PrimeField, BaseField: PrimeField> Reducer<TargetField, BaseFi
|
||||
for (group_id, (left_total_limb, right_total_limb, num_limb_in_this_group)) in
|
||||
groupped_limb_pairs.iter().enumerate()
|
||||
{
|
||||
let mut pad_limb_repr: <BaseField as PrimeField>::BigInt =
|
||||
BaseField::one().into_bigint();
|
||||
let mut pad_limb_repr = BaseField::ONE.into_bigint();
|
||||
|
||||
pad_limb_repr.muln(
|
||||
(surfeit
|
||||
+ (bits_per_limb - shift_per_limb)
|
||||
+ shift_per_limb * num_limb_in_this_group
|
||||
+ 1
|
||||
+ 1) as u32,
|
||||
);
|
||||
pad_limb_repr <<= (surfeit
|
||||
+ (bits_per_limb - shift_per_limb)
|
||||
+ shift_per_limb * num_limb_in_this_group
|
||||
+ 1
|
||||
+ 1) as u32;
|
||||
let pad_limb = BaseField::from_bigint(pad_limb_repr).unwrap();
|
||||
|
||||
let left_total_limb_value = left_total_limb.value().unwrap_or_default();
|
||||
@@ -298,12 +295,12 @@ impl<TargetField: PrimeField, BaseField: PrimeField> Reducer<TargetField, BaseFi
|
||||
let mut carry_value =
|
||||
left_total_limb_value + carry_in_value + pad_limb - right_total_limb_value;
|
||||
|
||||
let mut carry_repr = carry_value.into_bigint();
|
||||
carry_repr.divn((shift_per_limb * num_limb_in_this_group) as u32);
|
||||
let carry_repr =
|
||||
carry_value.into_bigint() >> (shift_per_limb * num_limb_in_this_group) as u32;
|
||||
|
||||
carry_value = BaseField::from_bigint(carry_repr).unwrap();
|
||||
|
||||
let carry = FpVar::<BaseField>::new_witness(cs.clone(), || Ok(carry_value))?;
|
||||
let carry = FpVar::new_witness(cs.clone(), || Ok(carry_value))?;
|
||||
|
||||
accumulated_extra += limbs_to_bigint(bits_per_limb, &[pad_limb]);
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
use ark_ec::{
|
||||
short_weierstrass::{
|
||||
Affine as SWAffine, Projective as SWProjective, SWCurveConfig as SWModelParameters,
|
||||
},
|
||||
AffineRepr, CurveGroup,
|
||||
short_weierstrass::{Affine as SWAffine, Projective as SWProjective, SWCurveConfig},
|
||||
AffineRepr, CurveConfig, CurveGroup,
|
||||
};
|
||||
use ark_ff::{AdditiveGroup, BigInteger, BitIteratorBE, Field, One, PrimeField, Zero};
|
||||
use ark_ff::{AdditiveGroup, BitIteratorBE, Field, One, PrimeField, Zero};
|
||||
use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError};
|
||||
use ark_std::{borrow::Borrow, marker::PhantomData, ops::Mul};
|
||||
use non_zero_affine::NonZeroAffineVar;
|
||||
|
||||
use crate::fields::nonnative::NonNativeFieldVar;
|
||||
use crate::{fields::fp::FpVar, prelude::*, ToConstraintFieldGadget, Vec};
|
||||
|
||||
/// This module provides a generic implementation of G1 and G2 for
|
||||
@@ -33,16 +32,17 @@ pub mod mnt6;
|
||||
/// to zero. The [ProjectiveVar] gadget is the recommended way of working with
|
||||
/// elliptic curve points.
|
||||
pub mod non_zero_affine;
|
||||
|
||||
type BasePrimeField<P> = <<P as CurveConfig>::BaseField as Field>::BasePrimeField;
|
||||
|
||||
/// An implementation of arithmetic for Short Weierstrass curves that relies on
|
||||
/// the complete formulae derived in the paper of
|
||||
/// [[Renes, Costello, Batina 2015]](<https://eprint.iacr.org/2015/1060>).
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug, Clone)]
|
||||
#[must_use]
|
||||
pub struct ProjectiveVar<
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
> where
|
||||
pub struct ProjectiveVar<P: SWCurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>>
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
/// The x-coordinate.
|
||||
@@ -57,12 +57,10 @@ pub struct ProjectiveVar<
|
||||
|
||||
/// An affine representation of a curve point.
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug, Clone)]
|
||||
#[derivative(Debug(bound = "F: ark_std::fmt::Debug"), Clone(bound = "F: Clone"))]
|
||||
#[must_use]
|
||||
pub struct AffineVar<
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
> where
|
||||
pub struct AffineVar<P: SWCurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>>
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
/// The x-coordinate.
|
||||
@@ -70,18 +68,18 @@ pub struct AffineVar<
|
||||
/// The y-coordinate.
|
||||
pub y: F,
|
||||
/// Is `self` the point at infinity.
|
||||
pub infinity: Boolean<<P::BaseField as Field>::BasePrimeField>,
|
||||
pub infinity: Boolean<BasePrimeField<P>>,
|
||||
#[derivative(Debug = "ignore")]
|
||||
_params: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl<P, F> AffineVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
fn new(x: F, y: F, infinity: Boolean<<P::BaseField as Field>::BasePrimeField>) -> Self {
|
||||
fn new(x: F, y: F, infinity: Boolean<BasePrimeField<P>>) -> Self {
|
||||
Self {
|
||||
x,
|
||||
y,
|
||||
@@ -100,17 +98,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> ToConstraintFieldGadget<BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
F: ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField>,
|
||||
F: ToConstraintFieldGadget<BasePrimeField<P>>,
|
||||
{
|
||||
fn to_constraint_field(
|
||||
&self,
|
||||
) -> Result<Vec<FpVar<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
let mut res = Vec::<FpVar<<P::BaseField as Field>::BasePrimeField>>::new();
|
||||
fn to_constraint_field(&self) -> Result<Vec<FpVar<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut res = Vec::<FpVar<BasePrimeField<P>>>::new();
|
||||
|
||||
res.extend_from_slice(&self.x.to_constraint_field()?);
|
||||
res.extend_from_slice(&self.y.to_constraint_field()?);
|
||||
@@ -120,15 +116,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> R1CSVar<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
|
||||
impl<P, F> R1CSVar<BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
type Value = SWProjective<P>;
|
||||
|
||||
fn cs(&self) -> ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField> {
|
||||
fn cs(&self) -> ConstraintSystemRef<BasePrimeField<P>> {
|
||||
self.x.cs().or(self.y.cs()).or(self.z.cs())
|
||||
}
|
||||
|
||||
@@ -143,8 +139,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: SWModelParameters, F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>>
|
||||
ProjectiveVar<P, F>
|
||||
impl<P: SWCurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>> ProjectiveVar<P, F>
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
@@ -200,7 +195,7 @@ where
|
||||
/// is a constant or is a public input).
|
||||
#[tracing::instrument(target = "r1cs", skip(cs, f))]
|
||||
pub fn new_variable_omit_on_curve_check(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<SWProjective<P>, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -288,7 +283,7 @@ where
|
||||
&self,
|
||||
mul_result: &mut Self,
|
||||
multiple_of_power_of_two: &mut NonZeroAffineVar<P, F>,
|
||||
bits: &[&Boolean<<P::BaseField as Field>::BasePrimeField>],
|
||||
bits: &[&Boolean<BasePrimeField<P>>],
|
||||
) -> Result<(), SynthesisError> {
|
||||
let scalar_modulus_bits = <P::ScalarField as PrimeField>::MODULUS_BIT_SIZE as usize;
|
||||
|
||||
@@ -371,11 +366,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> CurveVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>
|
||||
for ProjectiveVar<P, F>
|
||||
impl<P, F> CurveVar<SWProjective<P>, BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
fn constant(g: SWProjective<P>) -> Self {
|
||||
@@ -387,13 +381,13 @@ where
|
||||
Self::new(F::zero(), F::one(), F::zero())
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
|
||||
fn is_zero(&self) -> Result<Boolean<BasePrimeField<P>>, SynthesisError> {
|
||||
self.z.is_zero()
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(cs, f))]
|
||||
fn new_variable_omit_prime_order_check(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<SWProjective<P>, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -503,7 +497,7 @@ where
|
||||
#[tracing::instrument(target = "r1cs", skip(bits))]
|
||||
fn scalar_mul_le<'a>(
|
||||
&self,
|
||||
bits: impl Iterator<Item = &'a Boolean<<P::BaseField as Field>::BasePrimeField>>,
|
||||
bits: impl Iterator<Item = &'a Boolean<BasePrimeField<P>>>,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
if self.is_constant() {
|
||||
if self.value().unwrap().is_zero() {
|
||||
@@ -565,7 +559,7 @@ where
|
||||
) -> Result<(), SynthesisError>
|
||||
where
|
||||
I: Iterator<Item = (B, &'a SWProjective<P>)>,
|
||||
B: Borrow<Boolean<<P::BaseField as Field>::BasePrimeField>>,
|
||||
B: Borrow<Boolean<BasePrimeField<P>>>,
|
||||
{
|
||||
// We just ignore the provided bases and use the faster scalar multiplication.
|
||||
let (bits, bases): (Vec<_>, Vec<_>) = scalar_bits_with_bases
|
||||
@@ -577,26 +571,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
|
||||
impl<P, F> ToConstraintFieldGadget<BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
F: ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField>,
|
||||
F: ToConstraintFieldGadget<BasePrimeField<P>>,
|
||||
{
|
||||
fn to_constraint_field(
|
||||
&self,
|
||||
) -> Result<Vec<FpVar<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_constraint_field(&self) -> Result<Vec<FpVar<BasePrimeField<P>>>, SynthesisError> {
|
||||
self.to_affine()?.to_constraint_field()
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_by_coeff_a<
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
>(
|
||||
f: &F,
|
||||
) -> F
|
||||
fn mul_by_coeff_a<P: SWCurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>>(f: &F) -> F
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
@@ -681,7 +668,7 @@ impl_bounded_ops!(
|
||||
|this: &'a ProjectiveVar<P, F>, other: SWProjective<P>| {
|
||||
this + ProjectiveVar::constant(other)
|
||||
},
|
||||
(F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>, P: SWModelParameters),
|
||||
(F: FieldVar<P::BaseField, BasePrimeField<P>>, P: SWCurveConfig),
|
||||
for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
);
|
||||
|
||||
@@ -694,36 +681,59 @@ impl_bounded_ops!(
|
||||
sub_assign,
|
||||
|this: &'a ProjectiveVar<P, F>, other: &'a ProjectiveVar<P, F>| this + other.negate().unwrap(),
|
||||
|this: &'a ProjectiveVar<P, F>, other: SWProjective<P>| this - ProjectiveVar::constant(other),
|
||||
(F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>, P: SWModelParameters),
|
||||
(F: FieldVar<P::BaseField, BasePrimeField<P>>, P: SWCurveConfig),
|
||||
for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>
|
||||
);
|
||||
|
||||
impl_bounded_ops_diff!(
|
||||
ProjectiveVar<P, F>,
|
||||
SWProjective<P>,
|
||||
NonNativeFieldVar<P::ScalarField, BasePrimeField<P>>,
|
||||
P::ScalarField,
|
||||
Mul,
|
||||
mul,
|
||||
MulAssign,
|
||||
mul_assign,
|
||||
|this: &'a ProjectiveVar<P, F>, other: &'a NonNativeFieldVar<P::ScalarField, BasePrimeField<P>>| {
|
||||
if this.is_constant() && other.is_constant() {
|
||||
assert!(this.is_constant() && other.is_constant());
|
||||
ProjectiveVar::constant(this.value().unwrap() * &other.value().unwrap())
|
||||
} else {
|
||||
let bits = other.to_bits_le().unwrap();
|
||||
this.scalar_mul_le(bits.iter()).unwrap()
|
||||
}
|
||||
},
|
||||
|this: &'a ProjectiveVar<P, F>, other: P::ScalarField| this * NonNativeFieldVar::constant(other),
|
||||
(F: FieldVar<P::BaseField, BasePrimeField<P>>, P: SWCurveConfig),
|
||||
for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
);
|
||||
|
||||
impl<'a, P, F> GroupOpsBounds<'a, SWProjective<P>, ProjectiveVar<P, F>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<'a, P, F> GroupOpsBounds<'a, SWProjective<P>, ProjectiveVar<P, F>> for &'a ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<P, F> CondSelectGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
|
||||
impl<P, F> CondSelectGadget<BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn conditionally_select(
|
||||
cond: &Boolean<<P::BaseField as Field>::BasePrimeField>,
|
||||
cond: &Boolean<BasePrimeField<P>>,
|
||||
true_value: &Self,
|
||||
false_value: &Self,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -735,17 +745,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> EqGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
|
||||
impl<P, F> EqGadget<BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn is_eq(
|
||||
&self,
|
||||
other: &Self,
|
||||
) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
|
||||
fn is_eq(&self, other: &Self) -> Result<Boolean<BasePrimeField<P>>, SynthesisError> {
|
||||
let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?;
|
||||
let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?;
|
||||
let coordinates_equal = x_equal.and(&y_equal)?;
|
||||
@@ -758,7 +765,7 @@ where
|
||||
fn conditional_enforce_equal(
|
||||
&self,
|
||||
other: &Self,
|
||||
condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
|
||||
condition: &Boolean<BasePrimeField<P>>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let x_equal = (&self.x * &other.z).is_eq(&(&other.x * &self.z))?;
|
||||
let y_equal = (&self.y * &other.z).is_eq(&(&other.y * &self.z))?;
|
||||
@@ -775,7 +782,7 @@ where
|
||||
fn conditional_enforce_not_equal(
|
||||
&self,
|
||||
other: &Self,
|
||||
condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
|
||||
condition: &Boolean<BasePrimeField<P>>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let is_equal = self.is_eq(other)?;
|
||||
is_equal
|
||||
@@ -784,14 +791,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> AllocVar<SWAffine<P>, <P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
|
||||
impl<P, F> AllocVar<SWAffine<P>, BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
fn new_variable<T: Borrow<SWAffine<P>>>(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -803,15 +810,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> AllocVar<SWProjective<P>, <P::BaseField as Field>::BasePrimeField>
|
||||
for ProjectiveVar<P, F>
|
||||
impl<P, F> AllocVar<SWProjective<P>, BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
fn new_variable<T: Borrow<SWProjective<P>>>(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -864,8 +870,7 @@ where
|
||||
|| {
|
||||
f().map(|g| {
|
||||
let g = g.into_affine();
|
||||
let mut power_of_two = P::ScalarField::one().into_bigint();
|
||||
power_of_two.muln(power_of_2);
|
||||
let power_of_two = P::ScalarField::ONE.into_bigint() << power_of_2;
|
||||
let power_of_two_inv = P::ScalarField::from_bigint(power_of_two)
|
||||
.and_then(|n| n.inverse())
|
||||
.unwrap();
|
||||
@@ -915,16 +920,14 @@ fn div2(limbs: &mut [u64]) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> ToBitsGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
|
||||
impl<P, F> ToBitsGadget<BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bits_le(
|
||||
&self,
|
||||
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_bits_le(&self) -> Result<Vec<Boolean<BasePrimeField<P>>>, SynthesisError> {
|
||||
let g = self.to_affine()?;
|
||||
let mut bits = g.x.to_bits_le()?;
|
||||
let y_bits = g.y.to_bits_le()?;
|
||||
@@ -934,9 +937,7 @@ where
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bits_le(
|
||||
&self,
|
||||
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<BasePrimeField<P>>>, SynthesisError> {
|
||||
let g = self.to_affine()?;
|
||||
let mut bits = g.x.to_non_unique_bits_le()?;
|
||||
let y_bits = g.y.to_non_unique_bits_le()?;
|
||||
@@ -946,16 +947,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> ToBytesGadget<<P::BaseField as Field>::BasePrimeField> for ProjectiveVar<P, F>
|
||||
impl<P, F> ToBytesGadget<BasePrimeField<P>> for ProjectiveVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(
|
||||
&self,
|
||||
) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let g = self.to_affine()?;
|
||||
let mut bytes = g.x.to_bytes()?;
|
||||
let y_bytes = g.y.to_bytes()?;
|
||||
@@ -966,9 +965,7 @@ where
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(
|
||||
&self,
|
||||
) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let g = self.to_affine()?;
|
||||
let mut bytes = g.x.to_non_unique_bytes()?;
|
||||
let y_bytes = g.y.to_non_unique_bytes()?;
|
||||
|
||||
@@ -8,7 +8,7 @@ use ark_std::ops::Add;
|
||||
#[derivative(Debug, Clone)]
|
||||
#[must_use]
|
||||
pub struct NonZeroAffineVar<
|
||||
P: SWModelParameters,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
> where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
@@ -23,7 +23,7 @@ pub struct NonZeroAffineVar<
|
||||
|
||||
impl<P, F> NonZeroAffineVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
@@ -140,7 +140,7 @@ where
|
||||
|
||||
impl<P, F> R1CSVar<<P::BaseField as Field>::BasePrimeField> for NonZeroAffineVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
@@ -157,7 +157,7 @@ where
|
||||
|
||||
impl<P, F> CondSelectGadget<<P::BaseField as Field>::BasePrimeField> for NonZeroAffineVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
@@ -177,7 +177,7 @@ where
|
||||
|
||||
impl<P, F> EqGadget<<P::BaseField as Field>::BasePrimeField> for NonZeroAffineVar<P, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
P: SWCurveConfig,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
use ark_ec::{
|
||||
models::CurveConfig,
|
||||
twisted_edwards::{
|
||||
Affine as TEAffine, MontCurveConfig as MontgomeryModelParameter,
|
||||
Projective as TEProjective, TECurveConfig as TEModelParameters,
|
||||
Affine as TEAffine, MontCurveConfig, Projective as TEProjective, TECurveConfig,
|
||||
},
|
||||
AdditiveGroup, AffineRepr, CurveGroup,
|
||||
};
|
||||
use ark_ff::{BigInteger, BitIteratorBE, Field, One, PrimeField, Zero};
|
||||
use ark_ff::{BitIteratorBE, Field, One, PrimeField, Zero};
|
||||
use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError};
|
||||
|
||||
use crate::fields::nonnative::NonNativeFieldVar;
|
||||
use crate::{prelude::*, ToConstraintFieldGadget, Vec};
|
||||
|
||||
use crate::fields::fp::FpVar;
|
||||
use ark_std::{borrow::Borrow, marker::PhantomData, ops::Mul};
|
||||
|
||||
type BasePrimeField<P> = <<P as CurveConfig>::BaseField as Field>::BasePrimeField;
|
||||
|
||||
/// An implementation of arithmetic for Montgomery curves that relies on
|
||||
/// incomplete addition formulae for the affine model, as outlined in the
|
||||
/// [EFD](https://www.hyperelliptic.org/EFD/g1p/auto-montgom.html).
|
||||
@@ -22,10 +25,8 @@ use ark_std::{borrow::Borrow, marker::PhantomData, ops::Mul};
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug, Clone)]
|
||||
#[must_use]
|
||||
pub struct MontgomeryAffineVar<
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
> where
|
||||
pub struct MontgomeryAffineVar<P: TECurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>>
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
/// The x-coordinate.
|
||||
@@ -42,15 +43,15 @@ mod montgomery_affine_impl {
|
||||
use ark_ff::Field;
|
||||
use core::ops::Add;
|
||||
|
||||
impl<P, F> R1CSVar<<P::BaseField as Field>::BasePrimeField> for MontgomeryAffineVar<P, F>
|
||||
impl<P, F> R1CSVar<BasePrimeField<P>> for MontgomeryAffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
type Value = (P::BaseField, P::BaseField);
|
||||
|
||||
fn cs(&self) -> ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField> {
|
||||
fn cs(&self) -> ConstraintSystemRef<BasePrimeField<P>> {
|
||||
self.x.cs().or(self.y.cs())
|
||||
}
|
||||
|
||||
@@ -61,10 +62,7 @@ mod montgomery_affine_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
> MontgomeryAffineVar<P, F>
|
||||
impl<P: TECurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>> MontgomeryAffineVar<P, F>
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
@@ -101,7 +99,7 @@ mod montgomery_affine_impl {
|
||||
/// corresponding affine Montgomery curve point.
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
pub fn new_witness_from_edwards(
|
||||
cs: ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>,
|
||||
cs: ConstraintSystemRef<BasePrimeField<P>>,
|
||||
p: &TEAffine<P>,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let montgomery_coords = Self::from_edwards_to_coords(p)?;
|
||||
@@ -160,8 +158,8 @@ mod montgomery_affine_impl {
|
||||
|
||||
impl<'a, P, F> Add<&'a MontgomeryAffineVar<P, F>> for MontgomeryAffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
type Output = MontgomeryAffineVar<P, F>;
|
||||
@@ -234,10 +232,8 @@ mod montgomery_affine_impl {
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug, Clone)]
|
||||
#[must_use]
|
||||
pub struct AffineVar<
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
> where
|
||||
pub struct AffineVar<P: TECurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>>
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
/// The x-coordinate.
|
||||
@@ -248,8 +244,7 @@ pub struct AffineVar<
|
||||
_params: PhantomData<P>,
|
||||
}
|
||||
|
||||
impl<P: TEModelParameters, F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>>
|
||||
AffineVar<P, F>
|
||||
impl<P: TECurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>> AffineVar<P, F>
|
||||
where
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
@@ -267,7 +262,7 @@ where
|
||||
/// is a constant or is a public input).
|
||||
#[tracing::instrument(target = "r1cs", skip(cs, f))]
|
||||
pub fn new_variable_omit_on_curve_check<T: Into<TEAffine<P>>>(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -292,16 +287,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: TEModelParameters, F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>>
|
||||
AffineVar<P, F>
|
||||
impl<P: TECurveConfig, F: FieldVar<P::BaseField, BasePrimeField<P>>> AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>
|
||||
+ ThreeBitCondNegLookupGadget<
|
||||
<P::BaseField as Field>::BasePrimeField,
|
||||
TableConstant = P::BaseField,
|
||||
>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>
|
||||
+ ThreeBitCondNegLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
/// Compute a scalar multiplication of `bases` with respect to `scalars`,
|
||||
@@ -315,7 +306,7 @@ where
|
||||
scalars: &[impl Borrow<[J]>],
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
J: Borrow<[Boolean<<P::BaseField as Field>::BasePrimeField>]>,
|
||||
J: Borrow<[Boolean<BasePrimeField<P>>]>,
|
||||
{
|
||||
const CHUNK_SIZE: usize = 3;
|
||||
let mut ed_result: Option<AffineVar<P, F>> = None;
|
||||
@@ -385,15 +376,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> R1CSVar<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> R1CSVar<BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
type Value = TEProjective<P>;
|
||||
|
||||
fn cs(&self) -> ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField> {
|
||||
fn cs(&self) -> ConstraintSystemRef<BasePrimeField<P>> {
|
||||
self.x.cs().or(self.y.cs())
|
||||
}
|
||||
|
||||
@@ -405,11 +396,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> CurveVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> CurveVar<TEProjective<P>, BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
fn constant(g: TEProjective<P>) -> Self {
|
||||
@@ -421,13 +412,13 @@ where
|
||||
Self::new(F::zero(), F::one())
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
|
||||
fn is_zero(&self) -> Result<Boolean<BasePrimeField<P>>, SynthesisError> {
|
||||
self.x.is_zero()?.and(&self.y.is_one()?)
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(cs, f))]
|
||||
fn new_variable_omit_prime_order_check(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<TEProjective<P>, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -531,7 +522,7 @@ where
|
||||
) -> Result<(), SynthesisError>
|
||||
where
|
||||
I: Iterator<Item = (B, &'a TEProjective<P>)>,
|
||||
B: Borrow<Boolean<<P::BaseField as Field>::BasePrimeField>>,
|
||||
B: Borrow<Boolean<BasePrimeField<P>>>,
|
||||
{
|
||||
let (bits, multiples): (Vec<_>, Vec<_>) = scalar_bits_with_base_multiples
|
||||
.map(|(bit, base)| (bit.borrow().clone(), *base))
|
||||
@@ -559,16 +550,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> AllocVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> AllocVar<TEProjective<P>, BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs", skip(cs, f))]
|
||||
fn new_variable<Point: Borrow<TEProjective<P>>>(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<Point, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -621,8 +612,7 @@ where
|
||||
|| {
|
||||
f().map(|g| {
|
||||
let g = g.into_affine();
|
||||
let mut power_of_two = P::ScalarField::one().into_bigint();
|
||||
power_of_two.muln(power_of_2);
|
||||
let power_of_two = P::ScalarField::ONE.into_bigint() << power_of_2;
|
||||
let power_of_two_inv = P::ScalarField::from_bigint(power_of_two)
|
||||
.and_then(|n| n.inverse())
|
||||
.unwrap();
|
||||
@@ -660,16 +650,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> AllocVar<TEAffine<P>, <P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> AllocVar<TEAffine<P>, BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs", skip(cs, f))]
|
||||
fn new_variable<Point: Borrow<TEAffine<P>>>(
|
||||
cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
|
||||
cs: impl Into<Namespace<BasePrimeField<P>>>,
|
||||
f: impl FnOnce() -> Result<Point, SynthesisError>,
|
||||
mode: AllocationMode,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -681,16 +671,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> ToConstraintFieldGadget<BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
|
||||
F: ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField>,
|
||||
F: ToConstraintFieldGadget<BasePrimeField<P>>,
|
||||
{
|
||||
fn to_constraint_field(
|
||||
&self,
|
||||
) -> Result<Vec<FpVar<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_constraint_field(&self) -> Result<Vec<FpVar<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut res = Vec::new();
|
||||
|
||||
res.extend_from_slice(&self.x.to_constraint_field()?);
|
||||
@@ -772,9 +760,9 @@ impl_bounded_ops!(
|
||||
},
|
||||
|this: &'a AffineVar<P, F>, other: TEProjective<P>| this + AffineVar::constant(other),
|
||||
(
|
||||
F :FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
|
||||
P: TEModelParameters,
|
||||
F :FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
),
|
||||
for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
);
|
||||
@@ -789,41 +777,68 @@ impl_bounded_ops!(
|
||||
|this: &'a AffineVar<P, F>, other: &'a AffineVar<P, F>| this + other.negate().unwrap(),
|
||||
|this: &'a AffineVar<P, F>, other: TEProjective<P>| this - AffineVar::constant(other),
|
||||
(
|
||||
F :FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
|
||||
P: TEModelParameters,
|
||||
F :FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
),
|
||||
for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>
|
||||
);
|
||||
|
||||
impl_bounded_ops_diff!(
|
||||
AffineVar<P, F>,
|
||||
TEProjective<P>,
|
||||
NonNativeFieldVar<P::ScalarField, BasePrimeField<P>>,
|
||||
P::ScalarField,
|
||||
Mul,
|
||||
mul,
|
||||
MulAssign,
|
||||
mul_assign,
|
||||
|this: &'a AffineVar<P, F>, other: &'a NonNativeFieldVar<P::ScalarField, BasePrimeField<P>>| {
|
||||
if this.is_constant() && other.is_constant() {
|
||||
assert!(this.is_constant() && other.is_constant());
|
||||
AffineVar::constant(this.value().unwrap() * &other.value().unwrap())
|
||||
} else {
|
||||
let bits = other.to_bits_le().unwrap();
|
||||
this.scalar_mul_le(bits.iter()).unwrap()
|
||||
}
|
||||
},
|
||||
|this: &'a AffineVar<P, F>, other: P::ScalarField| this * NonNativeFieldVar::constant(other),
|
||||
(
|
||||
F :FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
),
|
||||
for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
);
|
||||
|
||||
impl<'a, P, F> GroupOpsBounds<'a, TEProjective<P>, AffineVar<P, F>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<'a, P, F> GroupOpsBounds<'a, TEProjective<P>, AffineVar<P, F>> for &'a AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
|
||||
+ TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>
|
||||
+ TwoBitLookupGadget<BasePrimeField<P>, TableConstant = P::BaseField>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<P, F> CondSelectGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> CondSelectGadget<BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
#[inline]
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn conditionally_select(
|
||||
cond: &Boolean<<P::BaseField as Field>::BasePrimeField>,
|
||||
cond: &Boolean<BasePrimeField<P>>,
|
||||
true_value: &Self,
|
||||
false_value: &Self,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
@@ -834,17 +849,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> EqGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> EqGadget<BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn is_eq(
|
||||
&self,
|
||||
other: &Self,
|
||||
) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
|
||||
fn is_eq(&self, other: &Self) -> Result<Boolean<BasePrimeField<P>>, SynthesisError> {
|
||||
let x_equal = self.x.is_eq(&other.x)?;
|
||||
let y_equal = self.y.is_eq(&other.y)?;
|
||||
x_equal.and(&y_equal)
|
||||
@@ -855,7 +867,7 @@ where
|
||||
fn conditional_enforce_equal(
|
||||
&self,
|
||||
other: &Self,
|
||||
condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
|
||||
condition: &Boolean<BasePrimeField<P>>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
self.x.conditional_enforce_equal(&other.x, condition)?;
|
||||
self.y.conditional_enforce_equal(&other.y, condition)?;
|
||||
@@ -867,7 +879,7 @@ where
|
||||
fn conditional_enforce_not_equal(
|
||||
&self,
|
||||
other: &Self,
|
||||
condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
|
||||
condition: &Boolean<BasePrimeField<P>>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
self.is_eq(other)?
|
||||
.and(condition)?
|
||||
@@ -875,16 +887,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> ToBitsGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> ToBitsGadget<BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bits_le(
|
||||
&self,
|
||||
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_bits_le(&self) -> Result<Vec<Boolean<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bits = self.x.to_bits_le()?;
|
||||
let y_bits = self.y.to_bits_le()?;
|
||||
x_bits.extend_from_slice(&y_bits);
|
||||
@@ -892,9 +902,7 @@ where
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bits_le(
|
||||
&self,
|
||||
) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_non_unique_bits_le(&self) -> Result<Vec<Boolean<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bits = self.x.to_non_unique_bits_le()?;
|
||||
let y_bits = self.y.to_non_unique_bits_le()?;
|
||||
x_bits.extend_from_slice(&y_bits);
|
||||
@@ -903,16 +911,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, F> ToBytesGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
|
||||
impl<P, F> ToBytesGadget<BasePrimeField<P>> for AffineVar<P, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
|
||||
P: TECurveConfig,
|
||||
F: FieldVar<P::BaseField, BasePrimeField<P>>,
|
||||
for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_bytes(
|
||||
&self,
|
||||
) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bytes = self.x.to_bytes()?;
|
||||
let y_bytes = self.y.to_bytes()?;
|
||||
x_bytes.extend_from_slice(&y_bytes);
|
||||
@@ -920,9 +926,7 @@ where
|
||||
}
|
||||
|
||||
#[tracing::instrument(target = "r1cs")]
|
||||
fn to_non_unique_bytes(
|
||||
&self,
|
||||
) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
|
||||
fn to_non_unique_bytes(&self) -> Result<Vec<UInt8<BasePrimeField<P>>>, SynthesisError> {
|
||||
let mut x_bytes = self.x.to_non_unique_bytes()?;
|
||||
let y_bytes = self.y.to_non_unique_bytes()?;
|
||||
x_bytes.extend_from_slice(&y_bytes);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::prelude::*;
|
||||
use ark_ff::Field;
|
||||
use crate::{fields::nonnative::NonNativeFieldVar, prelude::*};
|
||||
use ark_ff::PrimeField;
|
||||
use ark_relations::r1cs::{Namespace, SynthesisError};
|
||||
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
||||
use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
|
||||
|
||||
use ark_ec::CurveGroup;
|
||||
use core::{borrow::Borrow, fmt::Debug};
|
||||
@@ -12,20 +12,20 @@ pub mod curves;
|
||||
pub use self::curves::short_weierstrass::{bls12, mnt4, mnt6};
|
||||
|
||||
/// A hack used to work around the lack of implied bounds.
|
||||
pub trait GroupOpsBounds<'a, F, T: 'a>:
|
||||
pub trait GroupOpsBounds<'a, G, T: 'a>:
|
||||
Sized
|
||||
+ Add<&'a T, Output = T>
|
||||
+ Sub<&'a T, Output = T>
|
||||
+ Add<T, Output = T>
|
||||
+ Sub<T, Output = T>
|
||||
+ Add<F, Output = T>
|
||||
+ Sub<F, Output = T>
|
||||
+ Add<G, Output = T>
|
||||
+ Sub<G, Output = T>
|
||||
{
|
||||
}
|
||||
|
||||
/// A variable that represents a curve point for
|
||||
/// the curve `C`.
|
||||
pub trait CurveVar<C: CurveGroup, ConstraintF: Field>:
|
||||
pub trait CurveVar<C: CurveGroup, ConstraintF: PrimeField>:
|
||||
'static
|
||||
+ Sized
|
||||
+ Clone
|
||||
@@ -44,6 +44,9 @@ pub trait CurveVar<C: CurveGroup, ConstraintF: Field>:
|
||||
+ SubAssign<C>
|
||||
+ AddAssign<Self>
|
||||
+ SubAssign<Self>
|
||||
+ Mul<NonNativeFieldVar<C::ScalarField, ConstraintF>, Output = Self>
|
||||
+ for<'a> Mul<&'a NonNativeFieldVar<C::ScalarField, ConstraintF>, Output = Self>
|
||||
+ MulAssign<NonNativeFieldVar<C::ScalarField, ConstraintF>>
|
||||
{
|
||||
/// Returns the constant `F::zero()`. This is the identity
|
||||
/// of the group.
|
||||
|
||||
107
src/macros.rs
107
src/macros.rs
@@ -51,7 +51,7 @@ macro_rules! impl_bounded_ops {
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
#[allow(unused_braces, clippy::redundant_closure_call)]
|
||||
fn $fn(self, other: Self) -> Self::Output {
|
||||
fn $fn(self, other: &'a $type) -> Self::Output {
|
||||
($impl)(self, other)
|
||||
}
|
||||
}
|
||||
@@ -165,3 +165,108 @@ macro_rules! impl_bounded_ops {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements arithmetic traits (eg: `Add`, `Sub`, `Mul`) for the given type
|
||||
/// using the impl in `$impl`.
|
||||
///
|
||||
/// Used primarily for implementing these traits for `FieldVar`s and
|
||||
/// `GroupVar`s.
|
||||
///
|
||||
/// When compared to `impl_ops`, this macro allows specifying additional trait
|
||||
/// bounds.
|
||||
#[macro_export]
|
||||
macro_rules! impl_bounded_ops_diff {
|
||||
(
|
||||
$type: ty,
|
||||
$native: ty,
|
||||
$other_type: ty,
|
||||
$other_native: ty,
|
||||
$trait: ident,
|
||||
$fn: ident,
|
||||
$assign_trait: ident,
|
||||
$assign_fn: ident,
|
||||
$impl: expr,
|
||||
$constant_impl: expr,
|
||||
($($params:tt)+),
|
||||
$($bounds:tt)*
|
||||
) => {
|
||||
impl<'a, $($params)+> core::ops::$trait<&'a $other_type> for &'a $type
|
||||
where
|
||||
$($bounds)*
|
||||
{
|
||||
type Output = $type;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
#[allow(unused_braces, clippy::redundant_closure_call)]
|
||||
fn $fn(self, other: &'a $other_type) -> Self::Output {
|
||||
($impl)(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $($params)+> core::ops::$trait<$other_type> for &'a $type
|
||||
where
|
||||
$($bounds)*
|
||||
{
|
||||
type Output = $type;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
#[allow(unused_braces)]
|
||||
fn $fn(self, other: $other_type) -> Self::Output {
|
||||
core::ops::$trait::$fn(self, &other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $($params)+> core::ops::$trait<&'a $other_type> for $type
|
||||
where
|
||||
$($bounds)*
|
||||
{
|
||||
type Output = $type;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
#[allow(unused_braces)]
|
||||
fn $fn(self, other: &'a $other_type) -> Self::Output {
|
||||
core::ops::$trait::$fn(&self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($params)+> core::ops::$trait<$other_type> for $type
|
||||
where
|
||||
|
||||
$($bounds)*
|
||||
{
|
||||
type Output = $type;
|
||||
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
#[allow(unused_braces)]
|
||||
fn $fn(self, other: $other_type) -> Self::Output {
|
||||
core::ops::$trait::$fn(&self, &other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($params)+> core::ops::$assign_trait<$other_type> for $type
|
||||
where
|
||||
|
||||
$($bounds)*
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
#[allow(unused_braces)]
|
||||
fn $assign_fn(&mut self, other: $other_type) {
|
||||
let result = core::ops::$trait::$fn(&*self, &other);
|
||||
*self = result
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, $($params)+> core::ops::$assign_trait<&'a $other_type> for $type
|
||||
where
|
||||
|
||||
$($bounds)*
|
||||
{
|
||||
#[tracing::instrument(target = "r1cs", skip(self))]
|
||||
#[allow(unused_braces)]
|
||||
fn $assign_fn(&mut self, other: &'a $other_type) {
|
||||
let result = core::ops::$trait::$fn(&*self, other);
|
||||
*self = result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ impl<P: Bls12Config> PairingVar<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Bls12Config> PG<Bls12<P>, P::Fp> for PairingVar<P> {
|
||||
impl<P: Bls12Config> PG<Bls12<P>> for PairingVar<P> {
|
||||
type G1Var = G1Var<P>;
|
||||
type G2Var = G2Var<P>;
|
||||
type G1PreparedVar = G1PreparedVar<P>;
|
||||
|
||||
@@ -196,7 +196,7 @@ impl<P: MNT4Config> PairingVar<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MNT4Config> PG<MNT4<P>, P::Fp> for PairingVar<P> {
|
||||
impl<P: MNT4Config> PG<MNT4<P>> for PairingVar<P> {
|
||||
type G1Var = G1Var<P>;
|
||||
type G2Var = G2Var<P>;
|
||||
type G1PreparedVar = G1PreparedVar<P>;
|
||||
|
||||
@@ -191,7 +191,7 @@ impl<P: MNT6Config> PairingVar<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: MNT6Config> PG<MNT6<P>, P::Fp> for PairingVar<P> {
|
||||
impl<P: MNT6Config> PG<MNT6<P>> for PairingVar<P> {
|
||||
type G1Var = G1Var<P>;
|
||||
type G2Var = G2Var<P>;
|
||||
type G1PreparedVar = G1PreparedVar<P>;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::prelude::*;
|
||||
use ark_ec::{pairing::Pairing, CurveGroup};
|
||||
use ark_ff::Field;
|
||||
use ark_ec::pairing::Pairing;
|
||||
use ark_relations::r1cs::SynthesisError;
|
||||
use core::fmt::Debug;
|
||||
|
||||
@@ -11,38 +10,35 @@ pub mod mnt4;
|
||||
/// This module implements pairings for MNT6 bilinear groups.
|
||||
pub mod mnt6;
|
||||
|
||||
type BasePrimeField<E> = <<E as Pairing>::BaseField as ark_ff::Field>::BasePrimeField;
|
||||
|
||||
/// Specifies the constraints for computing a pairing in the yybilinear group
|
||||
/// `E`.
|
||||
pub trait PairingVar<E: Pairing, ConstraintF: Field = <<E as Pairing>::G1 as CurveGroup>::BaseField>
|
||||
{
|
||||
pub trait PairingVar<E: Pairing> {
|
||||
/// An variable representing an element of `G1`.
|
||||
/// This is the R1CS equivalent of `E::G1Projective`.
|
||||
type G1Var: CurveVar<E::G1, ConstraintF>
|
||||
+ AllocVar<E::G1, ConstraintF>
|
||||
+ AllocVar<E::G1Affine, ConstraintF>;
|
||||
type G1Var: CurveVar<E::G1, BasePrimeField<E>>;
|
||||
|
||||
/// An variable representing an element of `G2`.
|
||||
/// This is the R1CS equivalent of `E::G2Projective`.
|
||||
type G2Var: CurveVar<E::G2, ConstraintF>
|
||||
+ AllocVar<E::G2, ConstraintF>
|
||||
+ AllocVar<E::G2Affine, ConstraintF>;
|
||||
type G2Var: CurveVar<E::G2, BasePrimeField<E>>;
|
||||
|
||||
/// An variable representing an element of `GT`.
|
||||
/// This is the R1CS equivalent of `E::GT`.
|
||||
type GTVar: FieldVar<E::TargetField, ConstraintF>;
|
||||
type GTVar: FieldVar<E::TargetField, BasePrimeField<E>>;
|
||||
|
||||
/// An variable representing cached precomputation that can speed up
|
||||
/// pairings computations. This is the R1CS equivalent of
|
||||
/// `E::G1Prepared`.
|
||||
type G1PreparedVar: ToBytesGadget<ConstraintF>
|
||||
+ AllocVar<E::G1Prepared, ConstraintF>
|
||||
type G1PreparedVar: ToBytesGadget<BasePrimeField<E>>
|
||||
+ AllocVar<E::G1Prepared, BasePrimeField<E>>
|
||||
+ Clone
|
||||
+ Debug;
|
||||
/// An variable representing cached precomputation that can speed up
|
||||
/// pairings computations. This is the R1CS equivalent of
|
||||
/// `E::G2Prepared`.
|
||||
type G2PreparedVar: ToBytesGadget<ConstraintF>
|
||||
+ AllocVar<E::G2Prepared, ConstraintF>
|
||||
type G2PreparedVar: ToBytesGadget<BasePrimeField<E>>
|
||||
+ AllocVar<E::G2Prepared, BasePrimeField<E>>
|
||||
+ Clone
|
||||
+ Debug;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/// Evaluation domains for polynomials.
|
||||
pub mod domain;
|
||||
/// Evaluations of polynomials over domains.
|
||||
pub mod evaluations;
|
||||
/// Modules for working with polynomials in coefficient forms.
|
||||
pub mod polynomial;
|
||||
|
||||
Reference in New Issue
Block a user