ark_r1cs_std/fields/mod.rs
1use ark_ff::{prelude::*, BitIteratorBE};
2use ark_relations::gr1cs::{ConstraintSystemRef, SynthesisError};
3use core::{
4 fmt::Debug,
5 iter::Sum,
6 ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign},
7};
8
9use crate::{
10 convert::{ToBitsGadget, ToBytesGadget, ToConstraintFieldGadget},
11 prelude::*,
12};
13
14/// This module contains a generic implementation of cubic extension field
15/// variables. That is, it implements the R1CS equivalent of
16/// `ark_ff::CubicExtField`.
17pub mod cubic_extension;
18/// This module contains a generic implementation of quadratic extension field
19/// variables. That is, it implements the R1CS equivalent of
20/// `ark_ff::QuadExtField`.
21pub mod quadratic_extension;
22
23/// This module contains a generic implementation of prime field variables.
24/// That is, it implements the R1CS equivalent of `ark_ff::Fp*`.
25pub mod fp;
26
27/// This module contains a generic implementation of "emulated" prime field
28/// variables. It emulates `Fp` arithmetic using `Fq` operations, where `p !=
29/// q`.
30pub mod emulated_fp;
31
32/// This module contains a generic implementation of the degree-12 tower
33/// extension field. That is, it implements the R1CS equivalent of
34/// `ark_ff::Fp12`
35pub mod fp12;
36/// This module contains a generic implementation of the degree-2 tower
37/// extension field. That is, it implements the R1CS equivalent of
38/// `ark_ff::Fp2`
39pub mod fp2;
40/// This module contains a generic implementation of the degree-3 tower
41/// extension field. That is, it implements the R1CS equivalent of
42/// `ark_ff::Fp3`
43pub mod fp3;
44/// This module contains a generic implementation of the degree-4 tower
45/// extension field. That is, it implements the R1CS equivalent of
46/// `ark_ff::Fp4`
47pub mod fp4;
48/// This module contains a generic implementation of the degree-6 tower
49/// extension field. That is, it implements the R1CS equivalent of
50/// `ark_ff::fp6_2over3::Fp6`
51pub mod fp6_2over3;
52/// This module contains a generic implementation of the degree-6 tower
53/// extension field. That is, it implements the R1CS equivalent of
54/// `ark_ff::fp6_3over2::Fp6`
55pub mod fp6_3over2;
56
57/// This trait is a hack used to work around the lack of implied bounds.
58pub trait FieldOpsBounds<'a, F, T: 'a>:
59 Sized
60 + Add<&'a T, Output = T>
61 + Sub<&'a T, Output = T>
62 + Mul<&'a T, Output = T>
63 + Add<T, Output = T>
64 + Sub<T, Output = T>
65 + Mul<T, Output = T>
66 + Add<F, Output = T>
67 + Sub<F, Output = T>
68 + Mul<F, Output = T>
69{
70}
71
72/// A variable representing a field. Corresponds to the native type `F`.
73pub trait FieldVar<F: Field, ConstraintF: PrimeField>:
74 'static
75 + Clone
76 + From<Boolean<ConstraintF>>
77 + GR1CSVar<ConstraintF, Value = F>
78 + EqGadget<ConstraintF>
79 + ToBitsGadget<ConstraintF>
80 + AllocVar<F, ConstraintF>
81 + ToBytesGadget<ConstraintF>
82 + CondSelectGadget<ConstraintF>
83 + ToConstraintFieldGadget<ConstraintF>
84 + for<'a> FieldOpsBounds<'a, F, Self>
85 + for<'a> AddAssign<&'a Self>
86 + for<'a> SubAssign<&'a Self>
87 + for<'a> MulAssign<&'a Self>
88 + AddAssign<Self>
89 + SubAssign<Self>
90 + MulAssign<Self>
91 + AddAssign<F>
92 + SubAssign<F>
93 + MulAssign<F>
94 + Sum<Self>
95 + for<'a> Sum<&'a Self>
96 + Debug
97{
98 /// Returns the constant `F::zero()`.
99 fn zero() -> Self;
100
101 /// Returns a `Boolean` representing whether `self == Self::zero()`.
102 fn is_zero(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
103 self.is_eq(&Self::zero())
104 }
105
106 /// Returns the constant `F::one()`.
107 fn one() -> Self;
108
109 /// Returns a `Boolean` representing whether `self == Self::one()`.
110 fn is_one(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
111 self.is_eq(&Self::one())
112 }
113
114 /// Returns a constant with value `v`.
115 ///
116 /// This *should not* allocate any variables.
117 fn constant(v: F) -> Self;
118
119 /// Computes `self + self`.
120 fn double(&self) -> Result<Self, SynthesisError> {
121 Ok(self.clone() + self)
122 }
123
124 /// Sets `self = self + self`.
125 fn double_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
126 *self = self.double()?;
127 Ok(self)
128 }
129
130 /// Coputes `-self`.
131 fn negate(&self) -> Result<Self, SynthesisError>;
132
133 /// Sets `self = -self`.
134 #[inline]
135 fn negate_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
136 *self = self.negate()?;
137 Ok(self)
138 }
139
140 /// Computes `self * self`.
141 ///
142 /// A default implementation is provided which just invokes the underlying
143 /// multiplication routine. However, this method should be specialized
144 /// for extension fields, where faster algorithms exist for squaring.
145 fn square(&self) -> Result<Self, SynthesisError> {
146 Ok(self.clone() * self)
147 }
148
149 /// Sets `self = self.square()`.
150 fn square_in_place(&mut self) -> Result<&mut Self, SynthesisError> {
151 *self = self.square()?;
152 Ok(self)
153 }
154
155 /// Enforces that `self * other == result`.
156 fn mul_equals(&self, other: &Self, result: &Self) -> Result<(), SynthesisError> {
157 let actual_result = self.clone() * other;
158 result.enforce_equal(&actual_result)
159 }
160
161 /// Enforces that `self * self == result`.
162 fn square_equals(&self, result: &Self) -> Result<(), SynthesisError> {
163 let actual_result = self.square()?;
164 result.enforce_equal(&actual_result)
165 }
166
167 /// Computes `result` such that `self * result == Self::one()`.
168 fn inverse(&self) -> Result<Self, SynthesisError>;
169
170 /// Returns `(self / d)`.
171 /// The constraint system will be unsatisfiable when `d = 0`.
172 fn mul_by_inverse(&self, d: &Self) -> Result<Self, SynthesisError> {
173 // Enforce that `d` is not zero.
174 d.enforce_not_equal(&Self::zero())?;
175 self.mul_by_inverse_unchecked(d)
176 }
177
178 /// Returns `(self / d)`.
179 ///
180 /// The precondition for this method is that `d != 0`. If `d == 0`, this
181 /// method offers no guarantees about the soundness of the resulting
182 /// constraint system. For example, if `self == d == 0`, the current
183 /// implementation allows the constraint system to be trivially satisfiable.
184 fn mul_by_inverse_unchecked(&self, d: &Self) -> Result<Self, SynthesisError> {
185 let cs = self.cs().or(d.cs());
186 match cs {
187 // If we're in the constant case, we just allocate a new constant having value equalling
188 // `self * d.inverse()`.
189 ConstraintSystemRef::None => Self::new_constant(
190 cs,
191 self.value()? * d.value()?.inverse().expect("division by zero"),
192 ),
193 // If not, we allocate `result` as a new witness having value `self * d.inverse()`,
194 // and check that `result * d = self`.
195 _ => {
196 let result = Self::new_witness(ark_relations::ns!(cs, "self * d_inv"), || {
197 Ok(self.value()? * &d.value()?.inverse().unwrap_or(F::ZERO))
198 })?;
199 result.mul_equals(d, self)?;
200 Ok(result)
201 },
202 }
203 }
204
205 /// Computes the inner product of `this` and `other`.
206 fn inner_product(this: &[Self], other: &[Self]) -> Result<Self, SynthesisError> {
207 if this.len() != other.len() {
208 return Err(SynthesisError::Unsatisfiable);
209 }
210 Ok(this.iter().zip(other).map(|(a, b)| a.clone() * b).sum())
211 }
212
213 /// Computes the frobenius map over `self`.
214 fn frobenius_map(&self, power: usize) -> Result<Self, SynthesisError>;
215
216 /// Sets `self = self.frobenius_map()`.
217 fn frobenius_map_in_place(&mut self, power: usize) -> Result<&mut Self, SynthesisError> {
218 *self = self.frobenius_map(power)?;
219 Ok(self)
220 }
221
222 /// Comptues `self^bits`, where `bits` is a *little-endian* bit-wise
223 /// decomposition of the exponent.
224 fn pow_le(&self, bits: &[Boolean<ConstraintF>]) -> Result<Self, SynthesisError> {
225 let mut res = Self::one();
226 let mut power = self.clone();
227 for bit in bits {
228 let tmp = res.clone() * &power;
229 res = bit.select(&tmp, &res)?;
230 power.square_in_place()?;
231 }
232 Ok(res)
233 }
234
235 /// Computes `self^S`, where S is interpreted as an little-endian
236 /// u64-decomposition of an integer.
237 fn pow_by_constant<S: AsRef<[u64]>>(&self, exp: S) -> Result<Self, SynthesisError> {
238 let mut res = Self::one();
239 for i in BitIteratorBE::without_leading_zeros(exp) {
240 res.square_in_place()?;
241 if i {
242 res *= self;
243 }
244 }
245 Ok(res)
246 }
247}