arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/groups/curves/twisted_edwards/mod.rs
r1cs-std/src/groups/curves/twisted_edwards/mod.rsRaw
   1use algebra::{
   2    curves::{
   3        twisted_edwards_extended::{GroupAffine as TEAffine, GroupProjective as TEProjective},
   4        AffineCurve, MontgomeryModelParameters, ProjectiveCurve, TEModelParameters,
   5    },
   6    BigInteger, BitIteratorBE, Field, One, PrimeField, Zero,
   7};
   8
   9use r1cs_core::{ConstraintSystemRef, Namespace, SynthesisError};
  10
  11use crate::{prelude::*, ToConstraintFieldGadget, Vec};
  12
  13use crate::fields::fp::FpVar;
  14use core::{borrow::Borrow, marker::PhantomData};
  15
  16/// An implementation of arithmetic for Montgomery curves that relies on
  17/// incomplete addition formulae for the affine model, as outlined in the
  18/// [EFD](https://www.hyperelliptic.org/EFD/g1p/auto-montgom.html).
  19///
  20/// This is intended for use primarily for implementing efficient
  21/// multi-scalar-multiplication in the Bowe-Hopwood-Pedersen hash.
  22#[derive(Derivative)]
  23#[derivative(Debug, Clone)]
  24#[must_use]
  25pub struct MontgomeryAffineVar<
  26    P: TEModelParameters,
  27    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
  28> where
  29    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
  30{
  31    /// The x-coordinate.
  32    pub x: F,
  33    /// The y-coordinate.
  34    pub y: F,
  35    #[derivative(Debug = "ignore")]
  36    _params: PhantomData<P>,
  37}
  38
  39mod montgomery_affine_impl {
  40    use super::*;
  41    use algebra::{twisted_edwards_extended::GroupAffine, Field};
  42    use core::ops::Add;
  43
  44    impl<P, F> R1CSVar<<P::BaseField as Field>::BasePrimeField> for MontgomeryAffineVar<P, F>
  45    where
  46        P: TEModelParameters,
  47        F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
  48        for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
  49    {
  50        type Value = (P::BaseField, P::BaseField);
  51
  52        fn cs(&self) -> Option<ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>> {
  53            self.x.cs().or(self.y.cs())
  54        }
  55
  56        fn value(&self) -> Result<Self::Value, SynthesisError> {
  57            let x = self.x.value()?;
  58            let y = self.y.value()?;
  59            Ok((x, y))
  60        }
  61    }
  62
  63    impl<
  64            P: TEModelParameters,
  65            F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
  66        > MontgomeryAffineVar<P, F>
  67    where
  68        for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
  69    {
  70        /// Constructs `Self` from an `(x, y)` coordinate pair.
  71        pub fn new(x: F, y: F) -> Self {
  72            Self {
  73                x,
  74                y,
  75                _params: PhantomData,
  76            }
  77        }
  78
  79        /// Converts a Twisted Edwards curve point to coordinates for the corresponding affine
  80        /// Montgomery curve point.
  81        #[tracing::instrument(target = "r1cs")]
  82        pub fn from_edwards_to_coords(
  83            p: &TEAffine<P>,
  84        ) -> Result<(P::BaseField, P::BaseField), SynthesisError> {
  85            let montgomery_point: GroupAffine<P> = if p.y == P::BaseField::one() {
  86                GroupAffine::zero()
  87            } else if p.x == P::BaseField::zero() {
  88                GroupAffine::new(P::BaseField::zero(), P::BaseField::zero())
  89            } else {
  90                let u =
  91                    (P::BaseField::one() + &p.y) * &(P::BaseField::one() - &p.y).inverse().unwrap();
  92                let v = u * &p.x.inverse().unwrap();
  93                GroupAffine::new(u, v)
  94            };
  95
  96            Ok((montgomery_point.x, montgomery_point.y))
  97        }
  98
  99        /// Converts a Twisted Edwards curve point to coordinates for the corresponding affine
 100        /// Montgomery curve point.
 101        #[tracing::instrument(target = "r1cs")]
 102        pub fn new_witness_from_edwards(
 103            cs: ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>,
 104            p: &TEAffine<P>,
 105        ) -> Result<Self, SynthesisError> {
 106            let montgomery_coords = Self::from_edwards_to_coords(p)?;
 107            let u = F::new_witness(r1cs_core::ns!(cs, "u"), || Ok(montgomery_coords.0))?;
 108            let v = F::new_witness(r1cs_core::ns!(cs, "v"), || Ok(montgomery_coords.1))?;
 109            Ok(Self::new(u, v))
 110        }
 111
 112        /// Converts `self` into a Twisted Edwards curve point variable.
 113        #[tracing::instrument(target = "r1cs")]
 114        pub fn into_edwards(&self) -> Result<AffineVar<P, F>, SynthesisError> {
 115            let cs = self.cs().unwrap_or(ConstraintSystemRef::None);
 116            // Compute u = x / y
 117            let u = F::new_witness(r1cs_core::ns!(cs, "u"), || {
 118                let y_inv = self
 119                    .y
 120                    .value()?
 121                    .inverse()
 122                    .ok_or(SynthesisError::DivisionByZero)?;
 123                Ok(self.x.value()? * &y_inv)
 124            })?;
 125
 126            u.mul_equals(&self.y, &self.x)?;
 127
 128            let v = F::new_witness(r1cs_core::ns!(cs, "v"), || {
 129                let mut t0 = self.x.value()?;
 130                let mut t1 = t0;
 131                t0 -= &P::BaseField::one();
 132                t1 += &P::BaseField::one();
 133
 134                Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?)
 135            })?;
 136
 137            let xplusone = &self.x + P::BaseField::one();
 138            let xminusone = &self.x - P::BaseField::one();
 139            v.mul_equals(&xplusone, &xminusone)?;
 140
 141            Ok(AffineVar::new(u, v))
 142        }
 143    }
 144
 145    impl<'a, P, F> Add<&'a MontgomeryAffineVar<P, F>> for MontgomeryAffineVar<P, F>
 146    where
 147        P: TEModelParameters,
 148        F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 149        for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 150    {
 151        type Output = MontgomeryAffineVar<P, F>;
 152
 153        #[tracing::instrument(target = "r1cs")]
 154        fn add(self, other: &'a Self) -> Self::Output {
 155            let cs = [&self, other].cs();
 156            let mode = if cs.is_none() || matches!(cs, Some(ConstraintSystemRef::None)) {
 157                AllocationMode::Constant
 158            } else {
 159                AllocationMode::Witness
 160            };
 161            let cs = cs.unwrap_or(ConstraintSystemRef::None);
 162
 163            let coeff_b = P::MontgomeryModelParameters::COEFF_B;
 164            let coeff_a = P::MontgomeryModelParameters::COEFF_A;
 165
 166            let lambda = F::new_variable(
 167                r1cs_core::ns!(cs, "lambda"),
 168                || {
 169                    let n = other.y.value()? - &self.y.value()?;
 170                    let d = other.x.value()? - &self.x.value()?;
 171                    Ok(n * &d.inverse().ok_or(SynthesisError::DivisionByZero)?)
 172                },
 173                mode,
 174            )
 175            .unwrap();
 176            let lambda_n = &other.y - &self.y;
 177            let lambda_d = &other.x - &self.x;
 178            lambda_d.mul_equals(&lambda, &lambda_n).unwrap();
 179
 180            // Compute x'' = B*lambda^2 - A - x - x'
 181            let xprime = F::new_variable(
 182                r1cs_core::ns!(cs, "xprime"),
 183                || {
 184                    Ok(lambda.value()?.square() * &coeff_b
 185                        - &coeff_a
 186                        - &self.x.value()?
 187                        - &other.x.value()?)
 188                },
 189                mode,
 190            )
 191            .unwrap();
 192
 193            let xprime_lc = &self.x + &other.x + &xprime + coeff_a;
 194            // (lambda) * (lambda) = (A + x + x' + x'')
 195            let lambda_b = &lambda * coeff_b;
 196            lambda_b.mul_equals(&lambda, &xprime_lc).unwrap();
 197
 198            let yprime = F::new_variable(
 199                r1cs_core::ns!(cs, "yprime"),
 200                || {
 201                    Ok(-(self.y.value()?
 202                        + &(lambda.value()? * &(xprime.value()? - &self.x.value()?))))
 203                },
 204                mode,
 205            )
 206            .unwrap();
 207
 208            let xres = &self.x - &xprime;
 209            let yres = &self.y + &yprime;
 210            lambda.mul_equals(&xres, &yres).unwrap();
 211            MontgomeryAffineVar::new(xprime, yprime)
 212        }
 213    }
 214}
 215
 216/// An implementation of arithmetic for Twisted Edwards curves that relies on
 217/// the complete formulae for the affine model, as outlined in the
 218/// [EFD](https://www.hyperelliptic.org/EFD/g1p/auto-twisted.html).
 219#[derive(Derivative)]
 220#[derivative(Debug, Clone)]
 221#[must_use]
 222pub struct AffineVar<
 223    P: TEModelParameters,
 224    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 225> where
 226    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 227{
 228    /// The x-coordinate.
 229    pub x: F,
 230    /// The y-coordinate.
 231    pub y: F,
 232    #[derivative(Debug = "ignore")]
 233    _params: PhantomData<P>,
 234}
 235
 236impl<P: TEModelParameters, F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>>
 237    AffineVar<P, F>
 238where
 239    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 240{
 241    /// Constructs `Self` from an `(x, y)` coordinate triple.
 242    pub fn new(x: F, y: F) -> Self {
 243        Self {
 244            x,
 245            y,
 246            _params: PhantomData,
 247        }
 248    }
 249
 250    /// Allocates a new variable without performing an on-curve check, which is
 251    /// useful if the variable is known to be on the curve (eg., if the point
 252    /// is a constant or is a public input).
 253    #[tracing::instrument(target = "r1cs", skip(cs, f))]
 254    pub fn new_variable_omit_on_curve_check<T: Into<TEAffine<P>>>(
 255        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
 256        f: impl FnOnce() -> Result<T, SynthesisError>,
 257        mode: AllocationMode,
 258    ) -> Result<Self, SynthesisError> {
 259        let ns = cs.into();
 260        let cs = ns.cs();
 261
 262        let (x, y) = match f() {
 263            Ok(ge) => {
 264                let ge: TEAffine<P> = ge.into();
 265                (Ok(ge.x), Ok(ge.y))
 266            }
 267            _ => (
 268                Err(SynthesisError::AssignmentMissing),
 269                Err(SynthesisError::AssignmentMissing),
 270            ),
 271        };
 272
 273        let x = F::new_variable(r1cs_core::ns!(cs, "x"), || x, mode)?;
 274        let y = F::new_variable(r1cs_core::ns!(cs, "y"), || y, mode)?;
 275
 276        Ok(Self::new(x, y))
 277    }
 278}
 279
 280impl<P: TEModelParameters, F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>>
 281    AffineVar<P, F>
 282where
 283    P: TEModelParameters,
 284    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 285        + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>
 286        + ThreeBitCondNegLookupGadget<
 287            <P::BaseField as Field>::BasePrimeField,
 288            TableConstant = P::BaseField,
 289        >,
 290    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 291{
 292    /// Compute a scalar multiplication of `bases` with respect to `scalars`,
 293    /// where the elements of `scalars` are length-three slices of bits, and which
 294    /// such that the first two bits are use to select one of the bases,
 295    /// while the third bit is used to conditionally negate the selection.
 296    #[tracing::instrument(target = "r1cs", skip(bases, scalars))]
 297    pub fn precomputed_base_3_bit_signed_digit_scalar_mul<J>(
 298        bases: &[impl Borrow<[TEProjective<P>]>],
 299        scalars: &[impl Borrow<[J]>],
 300    ) -> Result<Self, SynthesisError>
 301    where
 302        J: Borrow<[Boolean<<P::BaseField as Field>::BasePrimeField>]>,
 303    {
 304        const CHUNK_SIZE: usize = 3;
 305        let mut ed_result: Option<AffineVar<P, F>> = None;
 306        let mut result: Option<MontgomeryAffineVar<P, F>> = None;
 307
 308        let mut process_segment_result = |result: &MontgomeryAffineVar<P, F>| {
 309            let sgmt_result = result.into_edwards()?;
 310            ed_result = match ed_result.as_ref() {
 311                None => Some(sgmt_result),
 312                Some(r) => Some(sgmt_result + r),
 313            };
 314            Ok::<(), SynthesisError>(())
 315        };
 316
 317        // Compute ∏(h_i^{m_i}) for all i.
 318        for (segment_bits_chunks, segment_powers) in scalars.iter().zip(bases) {
 319            for (bits, base_power) in segment_bits_chunks
 320                .borrow()
 321                .iter()
 322                .zip(segment_powers.borrow())
 323            {
 324                let base_power = base_power.borrow();
 325                let mut acc_power = *base_power;
 326                let mut coords = vec![];
 327                for _ in 0..4 {
 328                    coords.push(acc_power);
 329                    acc_power += base_power;
 330                }
 331
 332                let bits = bits.borrow().to_bits_le()?;
 333                if bits.len() != CHUNK_SIZE {
 334                    return Err(SynthesisError::Unsatisfiable);
 335                }
 336
 337                let coords = coords
 338                    .iter()
 339                    .map(|p| MontgomeryAffineVar::from_edwards_to_coords(&p.into_affine()))
 340                    .collect::<Result<Vec<_>, _>>()?;
 341
 342                let x_coeffs = coords.iter().map(|p| p.0).collect::<Vec<_>>();
 343                let y_coeffs = coords.iter().map(|p| p.1).collect::<Vec<_>>();
 344
 345                let precomp = bits[0].and(&bits[1])?;
 346
 347                let x = F::zero()
 348                    + x_coeffs[0]
 349                    + F::from(bits[0].clone()) * (x_coeffs[1] - &x_coeffs[0])
 350                    + F::from(bits[1].clone()) * (x_coeffs[2] - &x_coeffs[0])
 351                    + F::from(precomp.clone())
 352                        * (x_coeffs[3] - &x_coeffs[2] - &x_coeffs[1] + &x_coeffs[0]);
 353
 354                let y = F::three_bit_cond_neg_lookup(&bits, &precomp, &y_coeffs)?;
 355
 356                let tmp = MontgomeryAffineVar::new(x, y);
 357                result = match result.as_ref() {
 358                    None => Some(tmp),
 359                    Some(r) => Some(tmp + r),
 360                };
 361            }
 362
 363            process_segment_result(&result.unwrap())?;
 364            result = None;
 365        }
 366        if result.is_some() {
 367            process_segment_result(&result.unwrap())?;
 368        }
 369        Ok(ed_result.unwrap())
 370    }
 371}
 372
 373impl<P, F> R1CSVar<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 374where
 375    P: TEModelParameters,
 376    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 377    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 378{
 379    type Value = TEProjective<P>;
 380
 381    fn cs(&self) -> Option<ConstraintSystemRef<<P::BaseField as Field>::BasePrimeField>> {
 382        self.x.cs().or(self.y.cs())
 383    }
 384
 385    #[inline]
 386    fn value(&self) -> Result<TEProjective<P>, SynthesisError> {
 387        let (x, y) = (self.x.value()?, self.y.value()?);
 388        let result = TEAffine::new(x, y);
 389        Ok(result.into())
 390    }
 391}
 392
 393impl<P, F> CurveVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 394where
 395    P: TEModelParameters,
 396    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 397        + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
 398    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 399{
 400    fn constant(g: TEProjective<P>) -> Self {
 401        let cs = ConstraintSystemRef::None;
 402        Self::new_variable_omit_on_curve_check(cs, || Ok(g), AllocationMode::Constant).unwrap()
 403    }
 404
 405    fn zero() -> Self {
 406        Self::new(F::zero(), F::one())
 407    }
 408
 409    fn is_zero(&self) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
 410        self.x.is_zero()?.and(&self.x.is_one()?)
 411    }
 412
 413    #[tracing::instrument(target = "r1cs", skip(cs, f))]
 414    fn new_variable_omit_prime_order_check(
 415        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
 416        f: impl FnOnce() -> Result<TEProjective<P>, SynthesisError>,
 417        mode: AllocationMode,
 418    ) -> Result<Self, SynthesisError> {
 419        let ns = cs.into();
 420        let cs = ns.cs();
 421
 422        let g = Self::new_variable_omit_on_curve_check(cs, f, mode)?;
 423
 424        if mode != AllocationMode::Constant {
 425            let d = P::COEFF_D;
 426            let a = P::COEFF_A;
 427            // Check that ax^2 + y^2 = 1 + dx^2y^2
 428            // We do this by checking that ax^2 - 1 = y^2 * (dx^2 - 1)
 429            let x2 = g.x.square()?;
 430            let y2 = g.y.square()?;
 431
 432            let one = P::BaseField::one();
 433            let d_x2_minus_one = &x2 * d - one;
 434            let a_x2_minus_one = &x2 * a - one;
 435
 436            d_x2_minus_one.mul_equals(&y2, &a_x2_minus_one)?;
 437        }
 438        Ok(g)
 439    }
 440
 441    /// Enforce that `self` is in the prime-order subgroup.
 442    ///
 443    /// Does so by multiplying by the prime order, and checking that the result
 444    /// is unchanged.
 445    #[tracing::instrument(target = "r1cs")]
 446    fn enforce_prime_order(&self) -> Result<(), SynthesisError> {
 447        let r_minus_1 = (-P::ScalarField::one()).into_repr();
 448
 449        let mut result = Self::zero();
 450        for b in BitIteratorBE::without_leading_zeros(r_minus_1) {
 451            result.double_in_place()?;
 452
 453            if b {
 454                result += self;
 455            }
 456        }
 457        self.negate()?.enforce_equal(&result)?;
 458        Ok(())
 459    }
 460
 461    #[inline]
 462    #[tracing::instrument(target = "r1cs")]
 463    fn double_in_place(&mut self) -> Result<(), SynthesisError> {
 464        if let Some(cs) = self.cs() {
 465            let a = P::COEFF_A;
 466
 467            // xy
 468            let xy = &self.x * &self.y;
 469            let x2 = self.x.square()?;
 470            let y2 = self.y.square()?;
 471
 472            let a_x2 = &x2 * a;
 473
 474            // Compute x3 = (2xy) / (ax^2 + y^2)
 475            let x3 = F::new_witness(r1cs_core::ns!(cs, "x3"), || {
 476                let t0 = xy.value()?.double();
 477                let t1 = a * &x2.value()? + &y2.value()?;
 478                Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?)
 479            })?;
 480
 481            let a_x2_plus_y2 = &a_x2 + &y2;
 482            let two_xy = xy.double()?;
 483            x3.mul_equals(&a_x2_plus_y2, &two_xy)?;
 484
 485            // Compute y3 = (y^2 - ax^2) / (2 - ax^2 - y^2)
 486            let two = P::BaseField::one().double();
 487            let y3 = F::new_witness(r1cs_core::ns!(cs, "y3"), || {
 488                let a_x2 = a * &x2.value()?;
 489                let t0 = y2.value()? - &a_x2;
 490                let t1 = two - &a_x2 - &y2.value()?;
 491                Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?)
 492            })?;
 493            let y2_minus_a_x2 = &y2 - &a_x2;
 494            let two_minus_ax2_minus_y2 = (&a_x2 + &y2).negate()? + two;
 495
 496            y3.mul_equals(&two_minus_ax2_minus_y2, &y2_minus_a_x2)?;
 497            self.x = x3;
 498            self.y = y3;
 499        } else {
 500            let value = self.value()?;
 501            *self = Self::constant(value.double());
 502        }
 503        Ok(())
 504    }
 505
 506    #[tracing::instrument(target = "r1cs")]
 507    fn negate(&self) -> Result<Self, SynthesisError> {
 508        Ok(Self::new(self.x.negate()?, self.y.clone()))
 509    }
 510
 511    #[tracing::instrument(target = "r1cs", skip(scalar_bits_with_base_powers))]
 512    fn precomputed_base_scalar_mul_le<'a, I, B>(
 513        &mut self,
 514        scalar_bits_with_base_powers: I,
 515    ) -> Result<(), SynthesisError>
 516    where
 517        I: Iterator<Item = (B, &'a TEProjective<P>)>,
 518        B: Borrow<Boolean<<P::BaseField as Field>::BasePrimeField>>,
 519    {
 520        let scalar_bits_with_base_powers = scalar_bits_with_base_powers
 521            .map(|(bit, base)| (bit.borrow().clone(), (*base).into()))
 522            .collect::<Vec<(_, TEProjective<P>)>>();
 523        let zero = TEProjective::zero();
 524        for bits_base_powers in scalar_bits_with_base_powers.chunks(2) {
 525            if bits_base_powers.len() == 2 {
 526                let bits = [bits_base_powers[0].0.clone(), bits_base_powers[1].0.clone()];
 527                let base_powers = [&bits_base_powers[0].1, &bits_base_powers[1].1];
 528
 529                let mut table = [
 530                    zero,
 531                    *base_powers[0],
 532                    *base_powers[1],
 533                    *base_powers[0] + base_powers[1],
 534                ];
 535
 536                TEProjective::batch_normalization(&mut table);
 537                let x_s = [table[0].x, table[1].x, table[2].x, table[3].x];
 538                let y_s = [table[0].y, table[1].y, table[2].y, table[3].y];
 539
 540                let x = F::two_bit_lookup(&bits, &x_s)?;
 541                let y = F::two_bit_lookup(&bits, &y_s)?;
 542                *self += Self::new(x, y);
 543            } else if bits_base_powers.len() == 1 {
 544                let bit = bits_base_powers[0].0.clone();
 545                let base_power = bits_base_powers[0].1;
 546                let new_encoded = &*self + base_power;
 547                *self = bit.select(&new_encoded, &self)?;
 548            }
 549        }
 550
 551        Ok(())
 552    }
 553}
 554
 555impl<P, F> AllocVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 556where
 557    P: TEModelParameters,
 558    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 559        + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
 560    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 561{
 562    #[tracing::instrument(target = "r1cs", skip(cs, f))]
 563    fn new_variable<Point: Borrow<TEProjective<P>>>(
 564        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
 565        f: impl FnOnce() -> Result<Point, SynthesisError>,
 566        mode: AllocationMode,
 567    ) -> Result<Self, SynthesisError> {
 568        let ns = cs.into();
 569        let cs = ns.cs();
 570        let f = || Ok(*f()?.borrow());
 571        match mode {
 572            AllocationMode::Constant => Self::new_variable_omit_prime_order_check(cs, f, mode),
 573            AllocationMode::Input => Self::new_variable_omit_prime_order_check(cs, f, mode),
 574            AllocationMode::Witness => {
 575                // if cofactor.is_even():
 576                //   divide until you've removed all even factors
 577                // else:
 578                //   just directly use double and add.
 579                let mut power_of_2: u32 = 0;
 580                let mut cofactor = P::COFACTOR.to_vec();
 581                while cofactor[0] % 2 == 0 {
 582                    div2(&mut cofactor);
 583                    power_of_2 += 1;
 584                }
 585
 586                let cofactor_weight = BitIteratorBE::new(cofactor.as_slice())
 587                    .filter(|b| *b)
 588                    .count();
 589                let modulus_minus_1 = (-P::ScalarField::one()).into_repr(); // r - 1
 590                let modulus_minus_1_weight =
 591                    BitIteratorBE::new(modulus_minus_1).filter(|b| *b).count();
 592
 593                // We pick the most efficient method of performing the prime order check:
 594                // If the cofactor has lower hamming weight than the scalar field's modulus,
 595                // we first multiply by the inverse of the cofactor, and then, after allocating,
 596                // multiply by the cofactor. This ensures the resulting point has no cofactors
 597                //
 598                // Else, we multiply by the scalar field's modulus and ensure that the result
 599                // equals the identity.
 600
 601                let (mut ge, iter) = if cofactor_weight < modulus_minus_1_weight {
 602                    let ge = Self::new_variable_omit_prime_order_check(
 603                        r1cs_core::ns!(cs, "Witness without subgroup check with cofactor mul"),
 604                        || f().map(|g| g.borrow().into_affine().mul_by_cofactor_inv().into()),
 605                        mode,
 606                    )?;
 607                    (
 608                        ge,
 609                        BitIteratorBE::without_leading_zeros(cofactor.as_slice()),
 610                    )
 611                } else {
 612                    let ge = Self::new_variable_omit_prime_order_check(
 613                        r1cs_core::ns!(cs, "Witness without subgroup check with `r` check"),
 614                        || {
 615                            f().map(|g| {
 616                                let g = g.into_affine();
 617                                let mut power_of_two = P::ScalarField::one().into_repr();
 618                                power_of_two.muln(power_of_2);
 619                                let power_of_two_inv = P::ScalarField::from_repr(power_of_two)
 620                                    .and_then(|n| n.inverse())
 621                                    .unwrap();
 622                                g.mul(power_of_two_inv)
 623                            })
 624                        },
 625                        mode,
 626                    )?;
 627
 628                    (
 629                        ge,
 630                        BitIteratorBE::without_leading_zeros(modulus_minus_1.as_ref()),
 631                    )
 632                };
 633                // Remove the even part of the cofactor
 634                for _ in 0..power_of_2 {
 635                    ge.double_in_place()?;
 636                }
 637
 638                let mut result = Self::zero();
 639                for b in iter {
 640                    result.double_in_place()?;
 641                    if b {
 642                        result += &ge;
 643                    }
 644                }
 645                if cofactor_weight < modulus_minus_1_weight {
 646                    Ok(result)
 647                } else {
 648                    ge.enforce_equal(&ge)?;
 649                    Ok(ge)
 650                }
 651            }
 652        }
 653    }
 654}
 655
 656impl<P, F> AllocVar<TEAffine<P>, <P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 657where
 658    P: TEModelParameters,
 659    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 660        + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
 661    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 662{
 663    #[tracing::instrument(target = "r1cs", skip(cs, f))]
 664    fn new_variable<Point: Borrow<TEAffine<P>>>(
 665        cs: impl Into<Namespace<<P::BaseField as Field>::BasePrimeField>>,
 666        f: impl FnOnce() -> Result<Point, SynthesisError>,
 667        mode: AllocationMode,
 668    ) -> Result<Self, SynthesisError> {
 669        Self::new_variable(cs, || f().map(|b| b.borrow().into_projective()), mode)
 670    }
 671}
 672
 673impl<P, F> ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 674where
 675    P: TEModelParameters,
 676    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 677    for<'a> &'a F: FieldOpsBounds<'a, P::BaseField, F>,
 678    F: ToConstraintFieldGadget<<P::BaseField as Field>::BasePrimeField>,
 679{
 680    fn to_constraint_field(
 681        &self,
 682    ) -> Result<Vec<FpVar<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
 683        let mut res = Vec::new();
 684
 685        res.extend_from_slice(&self.x.to_constraint_field()?);
 686        res.extend_from_slice(&self.y.to_constraint_field()?);
 687
 688        Ok(res)
 689    }
 690}
 691
 692#[inline]
 693fn div2(limbs: &mut [u64]) {
 694    let mut t = 0;
 695    for i in limbs.iter_mut().rev() {
 696        let t2 = *i << 63;
 697        *i >>= 1;
 698        *i |= t;
 699        t = t2;
 700    }
 701}
 702
 703impl_bounded_ops!(
 704    AffineVar<P, F>,
 705    TEProjective<P>,
 706    Add,
 707    add,
 708    AddAssign,
 709    add_assign,
 710    |this: &'a AffineVar<P, F>, other: &'a AffineVar<P, F>| {
 711        if let Some(cs) = [this, other].cs() {
 712            let a = P::COEFF_A;
 713            let d = P::COEFF_D;
 714
 715            // Compute U = (x1 + y1) * (x2 + y2)
 716            let u1 = (&this.x * -a) + &this.y;
 717            let u2 = &other.x + &other.y;
 718
 719            let u = u1 *  &u2;
 720
 721            // Compute v0 = x1 * y2
 722            let v0 = &other.y * &this.x;
 723
 724            // Compute v1 = x2 * y1
 725            let v1 = &other.x * &this.y;
 726
 727            // Compute C = d*v0*v1
 728            let v2 = &v0 * &v1 * d;
 729
 730            // Compute x3 = (v0 + v1) / (1 + v2)
 731            let x3 = F::new_witness(r1cs_core::ns!(cs, "x3"), || {
 732                let t0 = v0.value()? + &v1.value()?;
 733                let t1 = P::BaseField::one() + &v2.value()?;
 734                Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?)
 735            }).unwrap();
 736
 737            let v2_plus_one = &v2 + P::BaseField::one();
 738            let v0_plus_v1 = &v0 + &v1;
 739            x3.mul_equals(&v2_plus_one, &v0_plus_v1).unwrap();
 740
 741            // Compute y3 = (U + a * v0 - v1) / (1 - v2)
 742            let y3 = F::new_witness(r1cs_core::ns!(cs, "y3"), || {
 743                let t0 = u.value()? + &(a * &v0.value()?) - &v1.value()?;
 744                let t1 = P::BaseField::one() - &v2.value()?;
 745                Ok(t0 * &t1.inverse().ok_or(SynthesisError::DivisionByZero)?)
 746            }).unwrap();
 747
 748            let one_minus_v2 = (&v2 - P::BaseField::one()).negate().unwrap();
 749            let a_v0 = &v0 * a;
 750            let u_plus_a_v0_minus_v1 = &u + &a_v0 - &v1;
 751
 752            y3.mul_equals(&one_minus_v2, &u_plus_a_v0_minus_v1).unwrap();
 753
 754            AffineVar::new(x3, y3)
 755        } else {
 756            assert!(this.is_constant() && other.is_constant());
 757            AffineVar::constant(this.value().unwrap() + &other.value().unwrap())
 758        }
 759    },
 760    |this: &'a AffineVar<P, F>, other: TEProjective<P>| this + AffineVar::constant(other),
 761    (
 762        F :FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 763            + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
 764        P: TEModelParameters,
 765    ),
 766    for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 767);
 768
 769impl_bounded_ops!(
 770    AffineVar<P, F>,
 771    TEProjective<P>,
 772    Sub,
 773    sub,
 774    SubAssign,
 775    sub_assign,
 776    |this: &'a AffineVar<P, F>, other: &'a AffineVar<P, F>| this + other.negate().unwrap(),
 777    |this: &'a AffineVar<P, F>, other: TEProjective<P>| this - AffineVar::constant(other),
 778    (
 779        F :FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 780            + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
 781        P: TEModelParameters,
 782    ),
 783    for <'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>
 784);
 785
 786impl<'a, P, F> GroupOpsBounds<'a, TEProjective<P>, AffineVar<P, F>> for AffineVar<P, F>
 787where
 788    P: TEModelParameters,
 789    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 790        + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
 791    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 792{
 793}
 794
 795impl<'a, P, F> GroupOpsBounds<'a, TEProjective<P>, AffineVar<P, F>> for &'a AffineVar<P, F>
 796where
 797    P: TEModelParameters,
 798    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>
 799        + TwoBitLookupGadget<<P::BaseField as Field>::BasePrimeField, TableConstant = P::BaseField>,
 800    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 801{
 802}
 803
 804impl<P, F> CondSelectGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 805where
 806    P: TEModelParameters,
 807    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 808    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 809{
 810    #[inline]
 811    #[tracing::instrument(target = "r1cs")]
 812    fn conditionally_select(
 813        cond: &Boolean<<P::BaseField as Field>::BasePrimeField>,
 814        true_value: &Self,
 815        false_value: &Self,
 816    ) -> Result<Self, SynthesisError> {
 817        let x = cond.select(&true_value.x, &false_value.x)?;
 818        let y = cond.select(&true_value.y, &false_value.y)?;
 819
 820        Ok(Self::new(x, y))
 821    }
 822}
 823
 824impl<P, F> EqGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 825where
 826    P: TEModelParameters,
 827    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 828    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 829{
 830    #[tracing::instrument(target = "r1cs")]
 831    fn is_eq(
 832        &self,
 833        other: &Self,
 834    ) -> Result<Boolean<<P::BaseField as Field>::BasePrimeField>, SynthesisError> {
 835        let x_equal = self.x.is_eq(&other.x)?;
 836        let y_equal = self.y.is_eq(&other.y)?;
 837        x_equal.and(&y_equal)
 838    }
 839
 840    #[inline]
 841    #[tracing::instrument(target = "r1cs")]
 842    fn conditional_enforce_equal(
 843        &self,
 844        other: &Self,
 845        condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
 846    ) -> Result<(), SynthesisError> {
 847        self.x.conditional_enforce_equal(&other.x, condition)?;
 848        self.y.conditional_enforce_equal(&other.y, condition)?;
 849        Ok(())
 850    }
 851
 852    #[inline]
 853    #[tracing::instrument(target = "r1cs")]
 854    fn conditional_enforce_not_equal(
 855        &self,
 856        other: &Self,
 857        condition: &Boolean<<P::BaseField as Field>::BasePrimeField>,
 858    ) -> Result<(), SynthesisError> {
 859        self.is_eq(other)?
 860            .and(condition)?
 861            .enforce_equal(&Boolean::Constant(false))
 862    }
 863}
 864
 865impl<P, F> ToBitsGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 866where
 867    P: TEModelParameters,
 868    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 869    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 870{
 871    #[tracing::instrument(target = "r1cs")]
 872    fn to_bits_le(
 873        &self,
 874    ) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
 875        let mut x_bits = self.x.to_bits_le()?;
 876        let y_bits = self.y.to_bits_le()?;
 877        x_bits.extend_from_slice(&y_bits);
 878        Ok(x_bits)
 879    }
 880
 881    #[tracing::instrument(target = "r1cs")]
 882    fn to_non_unique_bits_le(
 883        &self,
 884    ) -> Result<Vec<Boolean<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
 885        let mut x_bits = self.x.to_non_unique_bits_le()?;
 886        let y_bits = self.y.to_non_unique_bits_le()?;
 887        x_bits.extend_from_slice(&y_bits);
 888
 889        Ok(x_bits)
 890    }
 891}
 892
 893impl<P, F> ToBytesGadget<<P::BaseField as Field>::BasePrimeField> for AffineVar<P, F>
 894where
 895    P: TEModelParameters,
 896    F: FieldVar<P::BaseField, <P::BaseField as Field>::BasePrimeField>,
 897    for<'b> &'b F: FieldOpsBounds<'b, P::BaseField, F>,
 898{
 899    #[tracing::instrument(target = "r1cs")]
 900    fn to_bytes(
 901        &self,
 902    ) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
 903        let mut x_bytes = self.x.to_bytes()?;
 904        let y_bytes = self.y.to_bytes()?;
 905        x_bytes.extend_from_slice(&y_bytes);
 906        Ok(x_bytes)
 907    }
 908
 909    #[tracing::instrument(target = "r1cs")]
 910    fn to_non_unique_bytes(
 911        &self,
 912    ) -> Result<Vec<UInt8<<P::BaseField as Field>::BasePrimeField>>, SynthesisError> {
 913        let mut x_bytes = self.x.to_non_unique_bytes()?;
 914        let y_bytes = self.y.to_non_unique_bytes()?;
 915        x_bytes.extend_from_slice(&y_bytes);
 916
 917        Ok(x_bytes)
 918    }
 919}
 920
 921#[cfg(test)]
 922#[allow(dead_code)]
 923pub(crate) fn test<P, GG>() -> Result<(), SynthesisError>
 924where
 925    P: TEModelParameters,
 926    GG: CurveVar<TEProjective<P>, <P::BaseField as Field>::BasePrimeField>,
 927    for<'a> &'a GG: GroupOpsBounds<'a, TEProjective<P>, GG>,
 928{
 929    use crate::prelude::*;
 930    use algebra::{test_rng, BitIteratorLE, Group, UniformRand};
 931    use r1cs_core::ConstraintSystem;
 932
 933    crate::groups::test::group_test::<TEProjective<P>, _, GG>()?;
 934
 935    let mut rng = test_rng();
 936
 937    let cs = ConstraintSystem::<<P::BaseField as Field>::BasePrimeField>::new_ref();
 938
 939    let a = TEProjective::<P>::rand(&mut rng);
 940    let b = TEProjective::<P>::rand(&mut rng);
 941    let a_affine = a.into_affine();
 942    let b_affine = b.into_affine();
 943
 944    println!("Allocating things");
 945    let ns = r1cs_core::ns!(cs, "allocating variables");
 946    let mut gadget_a = GG::new_witness(cs.clone(), || Ok(a))?;
 947    let gadget_b = GG::new_witness(cs.clone(), || Ok(b))?;
 948    drop(ns);
 949    println!("Done Allocating things");
 950    assert_eq!(gadget_a.value()?.into_affine().x, a_affine.x);
 951    assert_eq!(gadget_a.value()?.into_affine().y, a_affine.y);
 952    assert_eq!(gadget_b.value()?.into_affine().x, b_affine.x);
 953    assert_eq!(gadget_b.value()?.into_affine().y, b_affine.y);
 954    assert_eq!(cs.which_is_unsatisfied()?, None);
 955
 956    println!("Checking addition");
 957    // Check addition
 958    let ab = a + &b;
 959    let ab_affine = ab.into_affine();
 960    let gadget_ab = &gadget_a + &gadget_b;
 961    let gadget_ba = &gadget_b + &gadget_a;
 962    gadget_ba.enforce_equal(&gadget_ab)?;
 963
 964    let ab_val = gadget_ab.value()?.into_affine();
 965    assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
 966    assert!(cs.is_satisfied().unwrap());
 967    println!("Done checking addition");
 968
 969    println!("Checking doubling");
 970    // Check doubling
 971    let aa = Group::double(&a);
 972    let aa_affine = aa.into_affine();
 973    gadget_a.double_in_place()?;
 974    let aa_val = gadget_a.value()?.into_affine();
 975    assert_eq!(
 976        aa_val, aa_affine,
 977        "Gadget and native values are unequal after double."
 978    );
 979    assert!(cs.is_satisfied().unwrap());
 980    println!("Done checking doubling");
 981
 982    println!("Checking mul_bits");
 983    // Check mul_bits
 984    let scalar = P::ScalarField::rand(&mut rng);
 985    let native_result = AffineCurve::mul(&aa.into_affine(), scalar);
 986    let native_result = native_result.into_affine();
 987
 988    let scalar: Vec<bool> = BitIteratorLE::new(scalar.into_repr()).collect();
 989    let input: Vec<Boolean<_>> =
 990        Vec::new_witness(r1cs_core::ns!(cs, "bits"), || Ok(scalar)).unwrap();
 991    let result = gadget_a.scalar_mul_le(input.iter())?;
 992    let result_val = result.value()?.into_affine();
 993    assert_eq!(
 994        result_val, native_result,
 995        "gadget & native values are diff. after scalar mul"
 996    );
 997    assert!(cs.is_satisfied().unwrap());
 998    println!("Done checking mul_bits");
 999
1000    if !cs.is_satisfied().unwrap() {
1001        println!("Not satisfied");
1002        println!("{:?}", cs.which_is_unsatisfied().unwrap());
1003    }
1004
1005    assert!(cs.is_satisfied().unwrap());
1006    Ok(())
1007}