arnaucube
arnaucube/ark-r1cs-stdPublic Self-hosted repository
ark-r1cs-std/r1cs-std/src/fields/mod.rs
r1cs-std/src/fields/mod.rsRaw
  1use algebra::{Field, fields::BitIterator};
  2use core::fmt::Debug;
  3use r1cs_core::{ConstraintSystem, SynthesisError};
  4
  5use crate::prelude::*;
  6
  7pub mod fp;
  8pub mod fp12;
  9pub mod fp2;
 10pub mod fp6_3over2;
 11
 12pub trait FieldGadget<F: Field, ConstraintF: Field>:
 13    Sized
 14    + Clone
 15    + EqGadget<ConstraintF>
 16    + NEqGadget<ConstraintF>
 17    + ConditionalEqGadget<ConstraintF>
 18    + ToBitsGadget<ConstraintF>
 19    + AllocGadget<F, ConstraintF>
 20    + ToBytesGadget<ConstraintF>
 21    + CondSelectGadget<ConstraintF>
 22    + TwoBitLookupGadget<ConstraintF, TableConstant = F>
 23    + ThreeBitCondNegLookupGadget<ConstraintF, TableConstant = F>
 24    + Debug
 25{
 26    type Variable: Clone + Debug;
 27
 28    fn get_value(&self) -> Option<F>;
 29
 30    fn get_variable(&self) -> Self::Variable;
 31
 32    fn zero<CS: ConstraintSystem<ConstraintF>>(_: CS) -> Result<Self, SynthesisError>;
 33
 34    fn one<CS: ConstraintSystem<ConstraintF>>(_: CS) -> Result<Self, SynthesisError>;
 35
 36    fn conditionally_add_constant<CS: ConstraintSystem<ConstraintF>>(
 37        &self,
 38        _: CS,
 39        _: &Boolean,
 40        _: F,
 41    ) -> Result<Self, SynthesisError>;
 42
 43    fn add<CS: ConstraintSystem<ConstraintF>>(
 44        &self,
 45        _: CS,
 46        _: &Self,
 47    ) -> Result<Self, SynthesisError>;
 48
 49    fn add_in_place<CS: ConstraintSystem<ConstraintF>>(
 50        &mut self,
 51        cs: CS,
 52        other: &Self,
 53    ) -> Result<&mut Self, SynthesisError> {
 54        *self = self.add(cs, other)?;
 55        Ok(self)
 56    }
 57
 58    fn double<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS) -> Result<Self, SynthesisError> {
 59        self.add(cs, &self)
 60    }
 61
 62    fn double_in_place<CS: ConstraintSystem<ConstraintF>>(
 63        &mut self,
 64        cs: CS,
 65    ) -> Result<&mut Self, SynthesisError> {
 66        *self = self.double(cs)?;
 67        Ok(self)
 68    }
 69
 70    fn sub<CS: ConstraintSystem<ConstraintF>>(
 71        &self,
 72        _: CS,
 73        _: &Self,
 74    ) -> Result<Self, SynthesisError>;
 75
 76    fn sub_in_place<CS: ConstraintSystem<ConstraintF>>(
 77        &mut self,
 78        cs: CS,
 79        other: &Self,
 80    ) -> Result<&mut Self, SynthesisError> {
 81        *self = self.sub(cs, other)?;
 82        Ok(self)
 83    }
 84
 85    fn negate<CS: ConstraintSystem<ConstraintF>>(&self, _: CS) -> Result<Self, SynthesisError>;
 86
 87    #[inline]
 88    fn negate_in_place<CS: ConstraintSystem<ConstraintF>>(
 89        &mut self,
 90        cs: CS,
 91    ) -> Result<&mut Self, SynthesisError> {
 92        *self = self.negate(cs)?;
 93        Ok(self)
 94    }
 95
 96    fn mul<CS: ConstraintSystem<ConstraintF>>(
 97        &self,
 98        _: CS,
 99        _: &Self,
100    ) -> Result<Self, SynthesisError>;
101
102    fn mul_in_place<CS: ConstraintSystem<ConstraintF>>(
103        &mut self,
104        cs: CS,
105        other: &Self,
106    ) -> Result<&mut Self, SynthesisError> {
107        *self = self.mul(cs, other)?;
108        Ok(self)
109    }
110
111    fn square<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS) -> Result<Self, SynthesisError> {
112        self.mul(cs, &self)
113    }
114
115    fn square_in_place<CS: ConstraintSystem<ConstraintF>>(
116        &mut self,
117        cs: CS,
118    ) -> Result<&mut Self, SynthesisError> {
119        *self = self.square(cs)?;
120        Ok(self)
121    }
122
123    fn mul_equals<CS: ConstraintSystem<ConstraintF>>(
124        &self,
125        mut cs: CS,
126        other: &Self,
127        result: &Self,
128    ) -> Result<(), SynthesisError> {
129        let actual_result = self.mul(cs.ns(|| "calc_actual_result"), other)?;
130        result.enforce_equal(&mut cs.ns(|| "test_equals"), &actual_result)
131    }
132
133    fn square_equals<CS: ConstraintSystem<ConstraintF>>(
134        &self,
135        mut cs: CS,
136        result: &Self,
137    ) -> Result<(), SynthesisError> {
138        let actual_result = self.square(cs.ns(|| "calc_actual_result"))?;
139        result.enforce_equal(&mut cs.ns(|| "test_equals"), &actual_result)
140    }
141
142    fn add_constant<CS: ConstraintSystem<ConstraintF>>(
143        &self,
144        _: CS,
145        _: &F,
146    ) -> Result<Self, SynthesisError>;
147
148    fn add_constant_in_place<CS: ConstraintSystem<ConstraintF>>(
149        &mut self,
150        cs: CS,
151        other: &F,
152    ) -> Result<&mut Self, SynthesisError> {
153        *self = self.add_constant(cs, other)?;
154        Ok(self)
155    }
156
157    fn sub_constant<CS: ConstraintSystem<ConstraintF>>(
158        &self,
159        cs: CS,
160        fe: &F,
161    ) -> Result<Self, SynthesisError> {
162        self.add_constant(cs, &(-(*fe)))
163    }
164
165    fn sub_constant_in_place<CS: ConstraintSystem<ConstraintF>>(
166        &mut self,
167        cs: CS,
168        other: &F,
169    ) -> Result<&mut Self, SynthesisError> {
170        self.add_constant_in_place(cs, &(-(*other)))
171    }
172
173    fn mul_by_constant<CS: ConstraintSystem<ConstraintF>>(
174        &self,
175        _: CS,
176        _: &F,
177    ) -> Result<Self, SynthesisError>;
178
179    fn mul_by_constant_in_place<CS: ConstraintSystem<ConstraintF>>(
180        &mut self,
181        cs: CS,
182        other: &F,
183    ) -> Result<&mut Self, SynthesisError> {
184        *self = self.mul_by_constant(cs, other)?;
185        Ok(self)
186    }
187
188    fn inverse<CS: ConstraintSystem<ConstraintF>>(&self, _: CS) -> Result<Self, SynthesisError>;
189
190    fn frobenius_map<CS: ConstraintSystem<ConstraintF>>(
191        &self,
192        _: CS,
193        power: usize,
194    ) -> Result<Self, SynthesisError>;
195
196    fn frobenius_map_in_place<CS: ConstraintSystem<ConstraintF>>(
197        &mut self,
198        cs: CS,
199        power: usize,
200    ) -> Result<&mut Self, SynthesisError> {
201        *self = self.frobenius_map(cs, power)?;
202        Ok(self)
203    }
204
205    /// Accepts as input a list of bits which, when interpreted in big-endian
206    /// form, are a scalar.
207    #[inline]
208    fn pow<CS: ConstraintSystem<ConstraintF>>(
209        &self,
210        mut cs: CS,
211        bits: &[Boolean],
212    ) -> Result<Self, SynthesisError> {
213        let mut res = Self::one(cs.ns(|| "Alloc result"))?;
214        for (i, bit) in bits.iter().enumerate() {
215            res = res.square(cs.ns(|| format!("Double {}", i)))?;
216            let tmp = res.mul(cs.ns(|| format!("Add {}-th base power", i)), self)?;
217            res = Self::conditionally_select(
218                cs.ns(|| format!("Conditional Select {}", i)),
219                bit,
220                &tmp,
221                &res,
222            )?;
223        }
224        Ok(res)
225    }
226
227    fn pow_by_constant<S: AsRef<[u64]>, CS: ConstraintSystem<ConstraintF>>(
228        &self,
229        mut cs: CS,
230        exp: S
231    ) -> Result<Self, SynthesisError> {
232        let mut res = Self::one(cs.ns(|| "Alloc result"))?;
233        let mut found_one = false;
234
235        for (i, bit) in BitIterator::new(exp).enumerate() {
236            if found_one {
237                res.square_in_place(cs.ns(|| format!("square for bit {:?}", i)))?;
238            }
239    
240            if !bit {
241                found_one = true;
242                res.mul_in_place(cs.ns(|| format!("mul for bit {:?}", i)), self)?;
243            }
244        }
245    
246        Ok(res)
247    }
248
249    fn cost_of_mul() -> usize;
250
251    fn cost_of_inv() -> usize;
252}
253
254#[cfg(test)]
255pub(crate) mod tests {
256    use rand::{self, SeedableRng};
257    use rand_xorshift::XorShiftRng;
258
259    use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
260    use algebra::{test_rng, BitIterator, Field, UniformRand};
261    use r1cs_core::ConstraintSystem;
262
263    #[allow(dead_code)]
264    pub(crate) fn field_test<FE: Field, ConstraintF: Field, F: FieldGadget<FE, ConstraintF>>() {
265        let mut cs = TestConstraintSystem::<ConstraintF>::new();
266
267        let mut rng = test_rng();
268        let a_native = FE::rand(&mut rng);
269        let b_native = FE::rand(&mut rng);
270        let a = F::alloc(&mut cs.ns(|| "generate_a"), || Ok(a_native)).unwrap();
271        let b = F::alloc(&mut cs.ns(|| "generate_b"), || Ok(b_native)).unwrap();
272
273        let zero = F::zero(cs.ns(|| "zero")).unwrap();
274        let zero_native = zero.get_value().unwrap();
275        zero.enforce_equal(&mut cs.ns(|| "zero_equals?"), &zero)
276            .unwrap();
277        assert_eq!(zero, zero);
278
279        let one = F::one(cs.ns(|| "one")).unwrap();
280        let one_native = one.get_value().unwrap();
281        assert_eq!(one, one);
282        one.enforce_equal(&mut cs.ns(|| "one_equals?"), &one)
283            .unwrap();
284        assert_ne!(one, zero);
285
286        let one_dup = zero.add(cs.ns(|| "zero_plus_one"), &one).unwrap();
287        one_dup
288            .enforce_equal(&mut cs.ns(|| "one_plus_zero_equals"), &one)
289            .unwrap();
290        assert_eq!(one_dup, one);
291
292        let two = one.add(cs.ns(|| "one_plus_one"), &one).unwrap();
293        two.enforce_equal(&mut cs.ns(|| "two_equals?"), &two)
294            .unwrap();
295        assert_eq!(two, two);
296        assert_ne!(zero, two);
297        assert_ne!(one, two);
298
299        // a == a
300        assert_eq!(a, a);
301
302        // a + 0 = a
303        let a_plus_zero = a.add(cs.ns(|| "a_plus_zero"), &zero).unwrap();
304        assert_eq!(a_plus_zero, a);
305        assert_eq!(a_plus_zero.get_value().unwrap(), a_native);
306        a_plus_zero
307            .enforce_equal(&mut cs.ns(|| "a_plus_zero_equals?"), &a)
308            .unwrap();
309
310        // a - 0 = a
311        let a_minus_zero = a.sub(cs.ns(|| "a_minus_zero"), &zero).unwrap();
312        assert_eq!(a_minus_zero, a);
313        assert_eq!(a_minus_zero.get_value().unwrap(), a_native);
314        a_minus_zero
315            .enforce_equal(&mut cs.ns(|| "a_minus_zero_equals?"), &a)
316            .unwrap();
317
318        // a - a = 0
319        let a_minus_a = a.sub(cs.ns(|| "a_minus_a"), &a).unwrap();
320        assert_eq!(a_minus_a, zero);
321        assert_eq!(a_minus_a.get_value().unwrap(), zero_native);
322        a_minus_a
323            .enforce_equal(&mut cs.ns(|| "a_minus_a_equals?"), &zero)
324            .unwrap();
325
326        // a + b = b + a
327        let a_b = a.add(cs.ns(|| "a_plus_b"), &b).unwrap();
328        let b_a = b.add(cs.ns(|| "b_plus_a"), &a).unwrap();
329        assert_eq!(a_b, b_a);
330        assert_eq!(a_b.get_value().unwrap(), a_native + &b_native);
331        a_b.enforce_equal(&mut cs.ns(|| "a+b == b+a"), &b_a)
332            .unwrap();
333
334        // (a + b) + a = a + (b + a)
335        let ab_a = a_b.add(cs.ns(|| "a_b_plus_a"), &a).unwrap();
336        let a_ba = a.add(cs.ns(|| "a_plus_b_a"), &b_a).unwrap();
337        assert_eq!(ab_a, a_ba);
338        assert_eq!(ab_a.get_value().unwrap(), a_native + &b_native + &a_native);
339        ab_a.enforce_equal(&mut cs.ns(|| "a+b + a == a+ b+a"), &a_ba)
340            .unwrap();
341
342        let b_times_a_plus_b = a_b.mul(cs.ns(|| "b * (a + b)"), &b).unwrap();
343        let b_times_b_plus_a = b_a.mul(cs.ns(|| "b * (b + a)"), &b).unwrap();
344        assert_eq!(b_times_b_plus_a, b_times_a_plus_b);
345        assert_eq!(
346            b_times_a_plus_b.get_value().unwrap(),
347            b_native * &(b_native + &a_native)
348        );
349        assert_eq!(
350            b_times_a_plus_b.get_value().unwrap(),
351            (b_native + &a_native) * &b_native
352        );
353        assert_eq!(
354            b_times_a_plus_b.get_value().unwrap(),
355            (a_native + &b_native) * &b_native
356        );
357        b_times_b_plus_a
358            .enforce_equal(&mut cs.ns(|| "b*(a+b) == b * (b+a)"), &b_times_a_plus_b)
359            .unwrap();
360
361        // a * 0 = 0
362        assert_eq!(a.mul(cs.ns(|| "a_times_zero"), &zero).unwrap(), zero);
363
364        // a * 1 = a
365        assert_eq!(a.mul(cs.ns(|| "a_times_one"), &one).unwrap(), a);
366        assert_eq!(
367            a.mul(cs.ns(|| "a_times_one2"), &one)
368                .unwrap()
369                .get_value()
370                .unwrap(),
371            a_native * &one_native
372        );
373
374        // a * b = b * a
375        let ab = a.mul(cs.ns(|| "a_times_b"), &b).unwrap();
376        let ba = b.mul(cs.ns(|| "b_times_a"), &a).unwrap();
377        assert_eq!(ab, ba);
378        assert_eq!(ab.get_value().unwrap(), a_native * &b_native);
379
380        // (a * b) * a = a * (b * a)
381        let ab_a = ab.mul(cs.ns(|| "ab_times_a"), &a).unwrap();
382        let a_ba = a.mul(cs.ns(|| "a_times_ba"), &ba).unwrap();
383        assert_eq!(ab_a, a_ba);
384        assert_eq!(ab_a.get_value().unwrap(), a_native * &b_native * &a_native);
385
386        let aa = a.mul(cs.ns(|| "a * a"), &a).unwrap();
387        let a_squared = a.square(cs.ns(|| "a^2")).unwrap();
388        a_squared
389            .enforce_equal(&mut cs.ns(|| "a^2 == a*a"), &aa)
390            .unwrap();
391        assert_eq!(aa, a_squared);
392        assert_eq!(aa.get_value().unwrap(), a_native.square());
393
394        let aa = a
395            .mul_by_constant(cs.ns(|| "a * a via mul_by_const"), &a.get_value().unwrap())
396            .unwrap();
397        a_squared
398            .enforce_equal(&mut cs.ns(|| "a^2 == a*a via mul_by_const"), &aa)
399            .unwrap();
400        assert_eq!(aa, a_squared);
401        assert_eq!(aa.get_value().unwrap(), a_native.square());
402
403        let a_b2 = a
404            .add_constant(cs.ns(|| "a + b via add_const"), &b.get_value().unwrap())
405            .unwrap();
406        a_b.enforce_equal(&mut cs.ns(|| "a + b == a + b via add_const"), &a_b2)
407            .unwrap();
408        assert_eq!(a_b, a_b2);
409
410        let a_inv = a.inverse(cs.ns(|| "a_inv")).unwrap();
411        a_inv
412            .mul_equals(cs.ns(|| "check_equals"), &a, &one)
413            .unwrap();
414        assert_eq!(
415            a_inv.get_value().unwrap(),
416            a.get_value().unwrap().inverse().unwrap()
417        );
418        assert_eq!(a_inv.get_value().unwrap(), a_native.inverse().unwrap());
419        // a * a * a = a^3
420        let bits = BitIterator::new([0x3])
421            .map(Boolean::constant)
422            .collect::<Vec<_>>();
423        assert_eq!(
424            a_native * &(a_native * &a_native),
425            a.pow(cs.ns(|| "test_pow"), &bits)
426                .unwrap()
427                .get_value()
428                .unwrap()
429        );
430
431        // a * a * a = a^3
432        assert_eq!(
433            a_native * &(a_native * &a_native),
434            a.pow_by_constant(cs.ns(|| "test_constant_pow"), &[3])
435                .unwrap()
436                .get_value()
437                .unwrap()
438        );
439
440        // a * a * a = a^3
441        let mut constants = [FE::zero(); 4];
442        for c in &mut constants {
443            *c = UniformRand::rand(&mut test_rng());
444            println!("Current c[i]: {:?}", c);
445        }
446        let bits = [Boolean::constant(false), Boolean::constant(true)];
447        let lookup_result =
448            F::two_bit_lookup(cs.ns(|| "Lookup"), &bits, constants.as_ref()).unwrap();
449        assert_eq!(lookup_result.get_value().unwrap(), constants[2]);
450
451        let negone: FE = UniformRand::rand(&mut test_rng());
452
453        let n = F::alloc(&mut cs.ns(|| "alloc new var"), || Ok(negone)).unwrap();
454        let _ = n.to_bytes(&mut cs.ns(|| "ToBytes")).unwrap();
455        let _ = n.to_bytes_strict(&mut cs.ns(|| "ToBytes Strict")).unwrap();
456
457        let ab_false = a
458            .conditionally_add_constant(
459                cs.ns(|| "Add bool with coeff false"),
460                &Boolean::constant(false),
461                b_native,
462            )
463            .unwrap();
464        assert_eq!(ab_false.get_value().unwrap(), a_native);
465        let ab_true = a
466            .conditionally_add_constant(
467                cs.ns(|| "Add bool with coeff true"),
468                &Boolean::constant(true),
469                b_native,
470            )
471            .unwrap();
472        assert_eq!(ab_true.get_value().unwrap(), a_native + &b_native);
473
474        if !cs.is_satisfied() {
475            println!("{:?}", cs.which_is_unsatisfied().unwrap());
476        }
477        assert!(cs.is_satisfied());
478    }
479
480    #[allow(dead_code)]
481    pub(crate) fn frobenius_tests<
482        FE: Field,
483        ConstraintF: Field,
484        F: FieldGadget<FE, ConstraintF>,
485    >(
486        maxpower: usize,
487    ) {
488        let mut cs = TestConstraintSystem::<ConstraintF>::new();
489        let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
490        for i in 0..=maxpower {
491            let mut a = FE::rand(&mut rng);
492            let mut a_gadget = F::alloc(cs.ns(|| format!("a_gadget_{:?}", i)), || Ok(a)).unwrap();
493            a_gadget = a_gadget
494                .frobenius_map(cs.ns(|| format!("frob_map_{}", i)), i)
495                .unwrap();
496            a.frobenius_map(i);
497
498            assert_eq!(a_gadget.get_value().unwrap(), a);
499        }
500
501        assert!(cs.is_satisfied());
502    }
503}