1#![allow(non_snake_case)]
2use core::borrow::Borrow;
3
4use ark_ec::AffineRepr;
5use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, prelude::*, R1CSVar};
6use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
7use ark_std::vec::Vec;
8
9use crate::ark_curve::r1cs::{lazy::LazyElementVar, FqVar};
10use crate::ark_curve::{edwards::EdwardsAffine, r1cs::inner::ElementVar as InnerElementVar};
11use crate::ark_curve::{AffinePoint, Element};
12use crate::Fq;
13
14use super::inner::Decaf377EdwardsVar;
15
16#[derive(Clone, Debug)]
17pub struct ElementVar {
22 pub(crate) inner: LazyElementVar,
23}
24
25impl ElementVar {
26 pub fn compress_to_field(&self) -> Result<FqVar, SynthesisError> {
28 self.inner.encoding()
29 }
30
31 pub fn decompress_from_field(s_var: FqVar) -> Result<ElementVar, SynthesisError> {
33 let inner = LazyElementVar::new_from_encoding(s_var);
34 inner.element()?;
36 Ok(Self { inner })
37 }
38
39 pub(crate) fn elligator_map(r_0_var: &FqVar) -> Result<ElementVar, SynthesisError> {
41 let inner = InnerElementVar::elligator_map(r_0_var)?;
42 Ok(Self {
43 inner: LazyElementVar::new_from_element(inner),
44 })
45 }
46
47 pub fn encode_to_curve(r_var: &FqVar) -> Result<ElementVar, SynthesisError> {
49 Self::elligator_map(r_var)
50 }
51}
52
53impl EqGadget<Fq> for ElementVar {
54 fn is_eq(&self, other: &Self) -> Result<Boolean<Fq>, SynthesisError> {
55 self.inner.element()?.is_eq(&other.inner.element()?)
56 }
57
58 fn conditional_enforce_equal(
59 &self,
60 other: &Self,
61 should_enforce: &Boolean<Fq>,
62 ) -> Result<(), SynthesisError> {
63 self.is_eq(other)?
68 .conditional_enforce_equal(&Boolean::constant(true), should_enforce)
69 }
70
71 fn conditional_enforce_not_equal(
72 &self,
73 other: &Self,
74 should_enforce: &Boolean<Fq>,
75 ) -> Result<(), SynthesisError> {
76 self.is_eq(other)?
77 .conditional_enforce_equal(&Boolean::constant(false), should_enforce)
78 }
79}
80
81impl R1CSVar<Fq> for ElementVar {
82 type Value = Element;
83
84 fn cs(&self) -> ConstraintSystemRef<Fq> {
85 let inner = self
86 .inner
87 .element()
88 .expect("element will exist if ElementVar is allocated");
89 inner.cs()
90 }
91
92 fn value(&self) -> Result<Self::Value, SynthesisError> {
93 let inner_element = self.inner.element()?;
94 let (x, y) = (
95 inner_element.inner.x.value()?,
96 inner_element.inner.y.value()?,
97 );
98 let result = EdwardsAffine::new(x, y);
99
100 Ok(Element {
101 inner: result.into(),
102 })
103 }
104}
105
106impl CondSelectGadget<Fq> for ElementVar {
107 fn conditionally_select(
108 cond: &Boolean<Fq>,
109 true_value: &Self,
110 false_value: &Self,
111 ) -> Result<Self, SynthesisError> {
112 let true_element = true_value.inner.element()?;
113 let false_element = false_value.inner.element()?;
114 let x = cond.select(&true_element.inner.x, &false_element.inner.x)?;
115 let y = cond.select(&true_element.inner.y, &false_element.inner.y)?;
116
117 let new_element = InnerElementVar {
118 inner: Decaf377EdwardsVar::new(x, y),
119 };
120 Ok(Self {
121 inner: LazyElementVar::new_from_element(new_element),
122 })
123 }
124}
125
126impl AllocVar<Element, Fq> for ElementVar {
129 fn new_variable<T: core::borrow::Borrow<Element>>(
130 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
131 f: impl FnOnce() -> Result<T, SynthesisError>,
132 mode: AllocationMode,
133 ) -> Result<Self, SynthesisError> {
134 let ns = cs.into();
135 let cs = ns.cs();
136 match mode {
137 AllocationMode::Input => {
138 let value: Element = *f()?.borrow();
139 let compressed = value.vartime_compress_to_field();
140 Ok(Self::new_input(cs, || Ok(compressed))?)
141 }
142 _ => {
143 let inner = InnerElementVar::new_variable(cs, f, mode)?;
144 Ok(Self {
145 inner: LazyElementVar::new_from_element(inner),
146 })
147 }
148 }
149 }
150}
151
152impl AllocVar<AffinePoint, Fq> for ElementVar {
153 fn new_variable<T: Borrow<AffinePoint>>(
154 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
155 f: impl FnOnce() -> Result<T, SynthesisError>,
156 mode: AllocationMode,
157 ) -> Result<Self, SynthesisError> {
158 Self::new_variable(cs, || f().map(|b| b.borrow().into_group()), mode)
159 }
160}
161
162impl AllocVar<Fq, Fq> for ElementVar {
163 fn new_variable<T: Borrow<Fq>>(
164 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
165 f: impl FnOnce() -> Result<T, SynthesisError>,
166 mode: AllocationMode,
167 ) -> Result<Self, SynthesisError> {
168 let ns = cs.into();
169 let cs = ns.cs();
170 let compressed = FqVar::new_variable(cs, f, mode)?;
171 Ok(Self {
172 inner: LazyElementVar::new_from_encoding(compressed),
173 })
174 }
175}
176
177impl ToBitsGadget<Fq> for ElementVar {
178 fn to_bits_le(&self) -> Result<Vec<Boolean<Fq>>, SynthesisError> {
179 let compressed_fq = self
180 .inner
181 .element()
182 .expect("element will exist")
183 .to_bits_le()?;
184 let encoded_bits = compressed_fq.to_bits_le()?;
185 Ok(encoded_bits)
186 }
187}
188
189impl ToBytesGadget<Fq> for ElementVar {
190 fn to_bytes(&self) -> Result<Vec<UInt8<Fq>>, SynthesisError> {
191 let compressed_fq = self
192 .inner
193 .element()
194 .expect("element will exist")
195 .to_bytes()?;
196 let encoded_bytes = compressed_fq.to_bytes()?;
197 Ok(encoded_bytes)
198 }
199}
200
201impl<'a> GroupOpsBounds<'a, Element, ElementVar> for ElementVar {}
202
203impl CurveVar<Element, Fq> for ElementVar {
204 fn zero() -> Self {
205 let new_element = InnerElementVar::zero();
206 Self {
207 inner: LazyElementVar::new_from_element(new_element),
208 }
209 }
210
211 fn constant(other: Element) -> Self {
212 let new_element = InnerElementVar::constant(other);
213 Self {
214 inner: LazyElementVar::new_from_element(new_element),
215 }
216 }
217
218 fn new_variable_omit_prime_order_check(
219 cs: impl Into<ark_relations::r1cs::Namespace<Fq>>,
220 f: impl FnOnce() -> Result<Element, SynthesisError>,
221 mode: AllocationMode,
222 ) -> Result<Self, SynthesisError> {
223 let ns = cs.into();
224 let cs = ns.cs();
225
226 match f() {
227 Ok(ge) => {
228 let new_element =
229 InnerElementVar::new_variable_omit_prime_order_check(cs, || Ok(ge), mode)?;
230 Ok(Self {
231 inner: LazyElementVar::new_from_element(new_element),
232 })
233 }
234 _ => Err(SynthesisError::AssignmentMissing),
235 }
236 }
237
238 fn enforce_prime_order(&self) -> Result<(), SynthesisError> {
239 Ok(())
241 }
242
243 fn double_in_place(&mut self) -> Result<(), SynthesisError> {
244 let mut inner_element = self.inner.element().expect("element will exist");
245 inner_element.double_in_place()?;
246 *self = Self {
247 inner: LazyElementVar::new_from_element(inner_element),
248 };
249 Ok(())
250 }
251
252 fn negate(&self) -> Result<Self, SynthesisError> {
253 let negated = self.inner.element().expect("element will exist").negate()?;
254 Ok(Self {
255 inner: LazyElementVar::new_from_element(negated),
256 })
257 }
258}