snarkvm_circuit_types_field/
lib.rs1#![forbid(unsafe_code)]
17#![allow(clippy::too_many_arguments)]
18#![cfg_attr(test, allow(clippy::assertions_on_result_states))]
19
20extern crate snarkvm_console_types_field as console;
21
22mod helpers;
23
24pub mod add;
25pub mod compare;
26pub mod div;
27pub mod div_unchecked;
28pub mod double;
29pub mod equal;
30pub mod inverse;
31pub mod mul;
32pub mod neg;
33pub mod pow;
34pub mod square;
35pub mod square_root;
36pub mod sub;
37pub mod ternary;
38
39#[cfg(test)]
40use console::{TestRng, Uniform};
41#[cfg(test)]
42use snarkvm_circuit_environment::{assert_count, assert_output_mode, assert_scope, count, output_mode};
43
44use snarkvm_circuit_environment::prelude::*;
45use snarkvm_circuit_types_boolean::Boolean;
46
47use std::cell::OnceCell;
48
49#[derive(Clone)]
50pub struct Field<E: Environment> {
51 linear_combination: LinearCombination<E::BaseField>,
53 bits_le: OnceCell<Vec<Boolean<E>>>,
56}
57
58impl<E: Environment> FieldTrait for Field<E> {}
59
60impl<E: Environment> Default for Field<E> {
61 fn default() -> Self {
63 Self::zero()
64 }
65}
66
67impl<E: Environment> Inject for Field<E> {
68 type Primitive = console::Field<E::Network>;
69
70 fn new(mode: Mode, field: Self::Primitive) -> Self {
72 Self { linear_combination: E::new_variable(mode, *field).into(), bits_le: Default::default() }
73 }
74}
75
76impl<E: Environment> Eject for Field<E> {
77 type Primitive = console::Field<E::Network>;
78
79 fn eject_mode(&self) -> Mode {
81 self.linear_combination.mode()
82 }
83
84 fn eject_value(&self) -> Self::Primitive {
86 console::Field::new(self.linear_combination.value())
87 }
88}
89
90impl<E: Environment> Parser for Field<E> {
91 #[inline]
93 fn parse(string: &str) -> ParserResult<Self> {
94 let (string, field) = console::Field::parse(string)?;
96 let (string, mode) = opt(pair(tag("."), Mode::parse))(string)?;
98
99 match mode {
100 Some((_, mode)) => Ok((string, Field::new(mode, field))),
101 None => Ok((string, Field::new(Mode::Constant, field))),
102 }
103 }
104}
105
106impl<E: Environment> FromStr for Field<E> {
107 type Err = Error;
108
109 #[inline]
111 fn from_str(string: &str) -> Result<Self> {
112 match Self::parse(string) {
113 Ok((remainder, object)) => {
114 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\"");
116 Ok(object)
118 }
119 Err(error) => bail!("Failed to parse string. {error}"),
120 }
121 }
122}
123
124impl<E: Environment> TypeName for Field<E> {
125 #[inline]
127 fn type_name() -> &'static str {
128 console::Field::<E::Network>::type_name()
129 }
130}
131
132impl<E: Environment> Debug for Field<E> {
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 Display::fmt(self, f)
135 }
136}
137
138impl<E: Environment> Display for Field<E> {
139 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
140 write!(f, "{}.{}", self.eject_value(), self.eject_mode())
141 }
142}
143
144impl<E: Environment> From<LinearCombination<E::BaseField>> for Field<E> {
145 fn from(linear_combination: LinearCombination<E::BaseField>) -> Self {
146 Self { linear_combination, bits_le: Default::default() }
147 }
148}
149
150impl<E: Environment> From<&LinearCombination<E::BaseField>> for Field<E> {
151 fn from(linear_combination: &LinearCombination<E::BaseField>) -> Self {
152 From::from(linear_combination.clone())
153 }
154}
155
156impl<E: Environment> From<Field<E>> for LinearCombination<E::BaseField> {
157 fn from(field: Field<E>) -> Self {
158 From::from(&field)
159 }
160}
161
162impl<E: Environment> From<&Field<E>> for LinearCombination<E::BaseField> {
163 fn from(field: &Field<E>) -> Self {
164 field.linear_combination.clone()
165 }
166}
167
168#[cfg(test)]
169mod tests {
170 use super::*;
171 use snarkvm_circuit_environment::Circuit;
172
173 const ITERATIONS: u64 = 10_000;
174
175 fn check_display(mode: Mode, element: console::Field<<Circuit as Environment>::Network>) -> Result<()> {
178 let candidate = Field::<Circuit>::new(mode, element);
179 assert_eq!(format!("{element}.{mode}"), format!("{candidate}"));
180
181 let candidate_recovered = Field::<Circuit>::from_str(&format!("{candidate}"))?;
182 assert_eq!(candidate.eject_value(), candidate_recovered.eject_value());
183 Ok(())
184 }
185
186 #[test]
187 fn test_display() -> Result<()> {
188 let mut rng = TestRng::default();
189
190 for _ in 0..ITERATIONS {
191 let element = Uniform::rand(&mut rng);
192
193 check_display(Mode::Constant, element)?;
195 check_display(Mode::Public, element)?;
197 check_display(Mode::Private, element)?;
199 }
200 Ok(())
201 }
202
203 #[test]
204 fn test_display_zero() {
205 let zero = console::Field::<<Circuit as Environment>::Network>::zero();
206
207 let candidate = Field::<Circuit>::new(Mode::Constant, zero);
209 assert_eq!("0field.constant", &format!("{candidate}"));
210
211 let candidate = Field::<Circuit>::new(Mode::Public, zero);
213 assert_eq!("0field.public", &format!("{candidate}"));
214
215 let candidate = Field::<Circuit>::new(Mode::Private, zero);
217 assert_eq!("0field.private", &format!("{candidate}"));
218 }
219
220 #[test]
221 fn test_display_one() {
222 let one = console::Field::<<Circuit as Environment>::Network>::one();
223
224 let candidate = Field::<Circuit>::new(Mode::Constant, one);
226 assert_eq!("1field.constant", &format!("{candidate}"));
227
228 let candidate = Field::<Circuit>::new(Mode::Public, one);
230 assert_eq!("1field.public", &format!("{candidate}"));
231
232 let candidate = Field::<Circuit>::new(Mode::Private, one);
234 assert_eq!("1field.private", &format!("{candidate}"));
235 }
236
237 #[test]
238 fn test_display_two() {
239 let one = console::Field::<<Circuit as Environment>::Network>::one();
240 let two = one + one;
241
242 let candidate = Field::<Circuit>::new(Mode::Constant, two);
244 assert_eq!("2field.constant", &format!("{candidate}"));
245
246 let candidate = Field::<Circuit>::new(Mode::Public, two);
248 assert_eq!("2field.public", &format!("{candidate}"));
249
250 let candidate = Field::<Circuit>::new(Mode::Private, two);
252 assert_eq!("2field.private", &format!("{candidate}"));
253 }
254
255 #[test]
256 fn test_parser() {
257 type Primitive = console::Field<<Circuit as Environment>::Network>;
258
259 let (_, candidate) = Field::<Circuit>::parse("5field").unwrap();
262 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
263 assert!(candidate.is_constant());
264
265 let (_, candidate) = Field::<Circuit>::parse("5_field").unwrap();
266 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
267 assert!(candidate.is_constant());
268
269 let (_, candidate) = Field::<Circuit>::parse("1_5_field").unwrap();
270 assert_eq!(Primitive::from_str("15field").unwrap(), candidate.eject_value());
271 assert!(candidate.is_constant());
272
273 let (_, candidate) = Field::<Circuit>::parse("5field.constant").unwrap();
274 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
275 assert!(candidate.is_constant());
276
277 let (_, candidate) = Field::<Circuit>::parse("5_field.constant").unwrap();
278 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
279 assert!(candidate.is_constant());
280
281 let (_, candidate) = Field::<Circuit>::parse("1_5_field.constant").unwrap();
282 assert_eq!(Primitive::from_str("15field").unwrap(), candidate.eject_value());
283 assert!(candidate.is_constant());
284
285 let (_, candidate) = Field::<Circuit>::parse("5field.public").unwrap();
288 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
289 assert!(candidate.is_public());
290
291 let (_, candidate) = Field::<Circuit>::parse("5_field.public").unwrap();
292 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
293 assert!(candidate.is_public());
294
295 let (_, candidate) = Field::<Circuit>::parse("1_5_field.public").unwrap();
296 assert_eq!(Primitive::from_str("15field").unwrap(), candidate.eject_value());
297 assert!(candidate.is_public());
298
299 let (_, candidate) = Field::<Circuit>::parse("5field.private").unwrap();
302 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
303 assert!(candidate.is_private());
304
305 let (_, candidate) = Field::<Circuit>::parse("5_field.private").unwrap();
306 assert_eq!(Primitive::from_str("5field").unwrap(), candidate.eject_value());
307 assert!(candidate.is_private());
308
309 let (_, candidate) = Field::<Circuit>::parse("1_5_field.private").unwrap();
310 assert_eq!(Primitive::from_str("15field").unwrap(), candidate.eject_value());
311 assert!(candidate.is_private());
312
313 let mut rng = TestRng::default();
316
317 for mode in [Mode::Constant, Mode::Public, Mode::Private] {
318 for _ in 0..ITERATIONS {
319 let value = Uniform::rand(&mut rng);
320 let expected = Field::<Circuit>::new(mode, value);
321
322 let (_, candidate) = Field::<Circuit>::parse(&format!("{expected}")).unwrap();
323 assert_eq!(expected.eject_value(), candidate.eject_value());
324 assert_eq!(mode, candidate.eject_mode());
325 }
326 }
327 }
328}