ark_r1cs_std/groups/
mod.rs1use crate::{
2 convert::{ToBitsGadget, ToBytesGadget, ToConstraintFieldGadget},
3 fields::emulated_fp::EmulatedFpVar,
4 prelude::*,
5};
6use ark_ff::PrimeField;
7use ark_relations::r1cs::{Namespace, SynthesisError};
8use core::ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign};
9
10use ark_ec::CurveGroup;
11use core::{borrow::Borrow, fmt::Debug};
12
13pub mod curves;
15
16pub use self::curves::short_weierstrass::{bls12, mnt4, mnt6};
17
18pub trait GroupOpsBounds<'a, G, T: 'a>:
20 Sized
21 + Add<&'a T, Output = T>
22 + Sub<&'a T, Output = T>
23 + Add<T, Output = T>
24 + Sub<T, Output = T>
25 + Add<G, Output = T>
26 + Sub<G, Output = T>
27{
28}
29
30pub trait CurveVar<C: CurveGroup, ConstraintF: PrimeField>:
33 'static
34 + Sized
35 + Clone
36 + Debug
37 + R1CSVar<ConstraintF, Value = C>
38 + ToBitsGadget<ConstraintF>
39 + ToBytesGadget<ConstraintF>
40 + EqGadget<ConstraintF>
41 + CondSelectGadget<ConstraintF>
42 + AllocVar<C, ConstraintF>
43 + AllocVar<C::Affine, ConstraintF>
44 + ToConstraintFieldGadget<ConstraintF>
45 + for<'a> GroupOpsBounds<'a, C, Self>
46 + for<'a> AddAssign<&'a Self>
47 + for<'a> SubAssign<&'a Self>
48 + AddAssign<C>
49 + SubAssign<C>
50 + AddAssign<Self>
51 + SubAssign<Self>
52 + Mul<EmulatedFpVar<C::ScalarField, ConstraintF>, Output = Self>
53 + for<'a> Mul<&'a EmulatedFpVar<C::ScalarField, ConstraintF>, Output = Self>
54 + MulAssign<EmulatedFpVar<C::ScalarField, ConstraintF>>
55{
56 fn zero() -> Self;
59
60 #[tracing::instrument(target = "r1cs")]
62 fn is_zero(&self) -> Result<Boolean<ConstraintF>, SynthesisError> {
63 self.is_eq(&Self::zero())
64 }
65
66 fn constant(other: C) -> Self;
70
71 fn new_variable_omit_prime_order_check(
74 cs: impl Into<Namespace<ConstraintF>>,
75 f: impl FnOnce() -> Result<C, SynthesisError>,
76 mode: AllocationMode,
77 ) -> Result<Self, SynthesisError>;
78
79 fn enforce_prime_order(&self) -> Result<(), SynthesisError>;
81
82 #[tracing::instrument(target = "r1cs")]
84 fn double(&self) -> Result<Self, SynthesisError> {
85 let mut result = self.clone();
86 result.double_in_place()?;
87 Ok(result)
88 }
89
90 fn double_in_place(&mut self) -> Result<(), SynthesisError>;
92
93 fn negate(&self) -> Result<Self, SynthesisError>;
95
96 #[tracing::instrument(target = "r1cs", skip(bits))]
99 fn scalar_mul_le<'a>(
100 &self,
101 bits: impl Iterator<Item = &'a Boolean<ConstraintF>>,
102 ) -> Result<Self, SynthesisError> {
103 let mut res = Self::zero();
109 let mut multiple = self.clone();
110 for bit in bits {
111 let tmp = res.clone() + &multiple;
112 res = bit.select(&tmp, &res)?;
113 multiple.double_in_place()?;
114 }
115 Ok(res)
116 }
117
118 #[tracing::instrument(target = "r1cs", skip(scalar_bits_with_bases))]
124 fn precomputed_base_scalar_mul_le<'a, I, B>(
125 &mut self,
126 scalar_bits_with_bases: I,
127 ) -> Result<(), SynthesisError>
128 where
129 I: Iterator<Item = (B, &'a C)>,
130 B: Borrow<Boolean<ConstraintF>>,
131 C: 'a,
132 {
133 let mut result = Self::zero();
138 for (bit, base) in scalar_bits_with_bases {
139 let self_plus_base = result.clone() + *base;
141 result = bit.borrow().select(&self_plus_base, &result)?;
144 }
145 *self += result;
146 Ok(())
147 }
148
149 #[tracing::instrument(target = "r1cs", skip(bases, scalars))]
153 fn precomputed_base_multiscalar_mul_le<'a, T, I, B>(
154 bases: &[B],
155 scalars: I,
156 ) -> Result<Self, SynthesisError>
157 where
158 T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
159 I: Iterator<Item = &'a T>,
160 B: Borrow<[C]>,
161 {
162 let mut result = Self::zero();
163 for (bits, bases) in scalars.zip(bases) {
165 let bases = bases.borrow();
166 let bits = bits.to_bits_le()?;
167 result.precomputed_base_scalar_mul_le(bits.iter().zip(bases))?;
168 }
169 Ok(result)
170 }
171}