arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/src/fields/mod.rs
src/fields/mod.rsRaw
  1use ark_ff::{prelude::*, BitIteratorBE};
  2use ark_relations::r1cs::SynthesisError;
  3use core::{
  4    fmt::Debug,
  5    ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
  6};
  7
  8use crate::{prelude::*, Assignment};
  9
 10/// This module contains a generic implementation of cubic extension field
 11/// variables. That is, it implements the R1CS equivalent of
 12/// `ark_ff::CubicExtField`.
 13pub mod cubic_extension;
 14/// This module contains a generic implementation of quadratic extension field
 15/// variables. That is, it implements the R1CS equivalent of
 16/// `ark_ff::QuadExtField`.
 17pub mod quadratic_extension;
 18
 19/// This module contains a generic implementation of prime field variables.
 20/// That is, it implements the R1CS equivalent of `ark_ff::Fp*`.
 21pub mod fp;
 22
 23/// This module contains a generic implementation of the degree-12 tower
 24/// extension field. That is, it implements the R1CS equivalent of
 25/// `ark_ff::Fp12`
 26pub mod fp12;
 27/// This module contains a generic implementation of the degree-2 tower
 28/// extension field. That is, it implements the R1CS equivalent of
 29/// `ark_ff::Fp2`
 30pub mod fp2;
 31/// This module contains a generic implementation of the degree-3 tower
 32/// extension field. That is, it implements the R1CS equivalent of
 33/// `ark_ff::Fp3`
 34pub mod fp3;
 35/// This module contains a generic implementation of the degree-4 tower
 36/// extension field. That is, it implements the R1CS equivalent of
 37/// `ark_ff::Fp4`
 38pub mod fp4;
 39/// This module contains a generic implementation of the degree-6 tower
 40/// extension field. That is, it implements the R1CS equivalent of
 41/// `ark_ff::fp6_2over3::Fp6`
 42pub mod fp6_2over3;
 43/// This module contains a generic implementation of the degree-6 tower
 44/// extension field. That is, it implements the R1CS equivalent of
 45/// `ark_ff::fp6_3over2::Fp6`
 46pub mod fp6_3over2;
 47
 48/// This trait is a hack used to work around the lack of implied bounds.
 49pub trait FieldOpsBounds<'a, F, T: 'a>:
 50    Sized
 51    + Add<&'a T, Output = T>
 52    + Sub<&'a T, Output = T>
 53    + Mul<&'a T, Output = T>
 54    + Add<T, Output = T>
 55    + Sub<T, Output = T>
 56    + Mul<T, Output = T>
 57    + Add<F, Output = T>
 58    + Sub<F, Output = T>
 59    + Mul<F, Output = T>
 60{
 61}
 62
 63/// A variable representing a field. Corresponds to the native type `F`.
 64pub trait FieldVar<F: Field, ConstraintF: Field>:
 65    'static
 66    + Clone
 67    + From<Boolean<ConstraintF>>
 68    + R1CSVar<ConstraintF, Value = F>
 69    + EqGadget<ConstraintF>
 70    + ToBitsGadget<ConstraintF>
 71    + AllocVar<F, ConstraintF>
 72    + ToBytesGadget<ConstraintF>
 73    + CondSelectGadget<ConstraintF>
 74    + for<'a> FieldOpsBounds<'a, F, Self>
 75    + for<'a> AddAssign<&'a Self>
 76    + for<'a> SubAssign<&'a Self>
 77    + for<'a> MulAssign<&'a Self>
 78    + AddAssign<Self>
 79    + SubAssign<Self>
 80    + MulAssign<Self>
 81    + AddAssign<F>
 82    + SubAssign<F>
 83    + MulAssign<F>
 84    + Debug
 85{
 86    /// Returns the constant `F::zero()`.
 87    fn zero() -> Self;
 88
 89    /// Returns a `Boolean` representing whether `self == Self::zero()`.
 90    fn is_zero(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
 91        self.is_eq(&Self::zero())
 92    }
 93
 94    /// Returns the constant `F::one()`.
 95    fn one() -> Self;
 96
 97    /// Returns a `Boolean` representing whether `self == Self::one()`.
 98    fn is_one(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
 99        self.is_eq(&Self::one())
100    }
101
102    /// Returns a constant with value `v`.
103    ///
104    /// This *should not* allocate any variables.
105    fn constant(v: F) -> Self;
106
107    /// Computes `self + self`.
108    fn double(&self) -> Result<Self, SynthesisError> {
109        Ok(self.clone() + self)
110    }
111
112    /// Sets `self = self + self`.
113    fn double_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
114        *self += self.double()?;
115        Ok(self)
116    }
117
118    /// Coputes `-self`.
119    fn negate(&self) -> Result<Self, SynthesisError>;
120
121    /// Sets `self = -self`.
122    #[inline]
123    fn negate_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
124        *self = self.negate()?;
125        Ok(self)
126    }
127
128    /// Computes `self * self`.
129    ///
130    /// A default implementation is provided which just invokes the underlying
131    /// multiplication routine. However, this method should be specialized
132    /// for extension fields, where faster algorithms exist for squaring.
133    fn square(&self) -> Result<Self, SynthesisError> {
134        Ok(self.clone() * self)
135    }
136
137    /// Sets `self = self.square()`.
138    fn square_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
139        *self = self.square()?;
140        Ok(self)
141    }
142
143    /// Enforces that `self * other == result`.
144    fn mul_equals(&self, other: &Self, result: &Self) -> Result<(), SynthesisError> {
145        let actual_result = self.clone() * other;
146        result.enforce_equal(&actual_result)
147    }
148
149    /// Enforces that `self * self == result`.
150    fn square_equals(&self, result: &Self) -> Result<(), SynthesisError> {
151        let actual_result = self.square()?;
152        result.enforce_equal(&actual_result)
153    }
154
155    /// Computes `result` such that `self * result == Self::one()`.
156    fn inverse(&self) -> Result<Self, SynthesisError>;
157
158    /// Returns `(self / denominator)`. but requires fewer constraints than
159    /// `self * denominator.inverse()`.
160    /// It is up to the caller to ensure that denominator is non-zero,
161    /// since in that case the result is unconstrained.
162    fn mul_by_inverse(&self, denominator: &Self) -> Result<Self, SynthesisError> {
163        if denominator.is_constant() {
164            Ok(denominator.inverse()? * self)
165        } else {
166            let result = Self::new_witness(self.cs(), || {
167                let denominator_inv_native = denominator.value()?.inverse().get()?;
168                let result = self.value()? * &denominator_inv_native;
169                Ok(result)
170            })?;
171            result.mul_equals(&denominator, &self)?;
172
173            Ok(result)
174        }
175    }
176
177    /// Computes the frobenius map over `self`.
178    fn frobenius_map(&self, power: usize) -> Result<Self, SynthesisError>;
179
180    /// Sets `self = self.frobenius_map()`.
181    fn frobenius_map_in_place(&mut self, power: usize) -> Result<&mut Self, SynthesisError> {
182        *self = self.frobenius_map(power)?;
183        Ok(self)
184    }
185
186    /// Comptues `self^bits`, where `bits` is a *little-endian* bit-wise
187    /// decomposition of the exponent.
188    fn pow_le(&self, bits: &[Boolean<ConstraintF>]) -> Result<Self, SynthesisError> {
189        let mut res = Self::one();
190        let mut power = self.clone();
191        for bit in bits {
192            let tmp = res.clone() * &power;
193            res = bit.select(&tmp, &res)?;
194            power.square_in_place()?;
195        }
196        Ok(res)
197    }
198
199    /// Computes `self^S`, where S is interpreted as an little-endian
200    /// u64-decomposition of an integer.
201    fn pow_by_constant<S: AsRef<[u64]>>(&self, exp: S) -> Result<Self, SynthesisError> {
202        let mut res = Self::one();
203        for i in BitIteratorBE::without_leading_zeros(exp) {
204            res.square_in_place()?;
205            if i {
206                res *= self;
207            }
208        }
209        Ok(res)
210    }
211}