1use std::cell::OnceCell;
17
18#[cfg(test)]
19use snarkvm_circuit_types::environment::assert_scope;
20
21mod encrypt;
22mod equal;
23mod find;
24mod from_bits;
25mod from_fields;
26mod num_randomizers;
27mod size_in_fields;
28mod to_bits;
29mod to_bits_raw;
30mod to_fields;
31mod to_fields_raw;
32
33use crate::{Access, Ciphertext, Identifier, Literal, Visibility};
34use console::PlaintextType;
35use snarkvm_circuit_network::Aleo;
36use snarkvm_circuit_types::{Address, Boolean, Field, Scalar, U8, U16, U32, environment::prelude::*};
37
38#[derive(Clone)]
39pub enum Plaintext<A: Aleo> {
40 Literal(Literal<A>, OnceCell<Vec<Boolean<A>>>),
42 Struct(IndexMap<Identifier<A>, Plaintext<A>>, OnceCell<Vec<Boolean<A>>>),
44 Array(Vec<Plaintext<A>>, OnceCell<Vec<Boolean<A>>>),
46}
47
48impl<A: Aleo> Plaintext<A> {
49 pub fn from_bit_array(bits: Vec<Boolean<A>>, length: u32) -> Result<Self> {
51 ensure!(bits.len() == length as usize, "Expected '{length}' bits, got '{}' bits", bits.len());
52 Ok(Self::Array(bits.into_iter().map(|bit| Plaintext::from(Literal::Boolean(bit))).collect(), OnceCell::new()))
53 }
54
55 pub fn as_bit_array(&self) -> Result<Vec<Boolean<A>>> {
57 match self {
58 Self::Array(elements, _) => {
59 let mut bits = Vec::with_capacity(elements.len());
60 for element in elements {
61 match element {
62 Self::Literal(Literal::Boolean(bit), _) => bits.push(bit.clone()),
63 _ => bail!("Expected a bit array, found a non-boolean element."),
64 }
65 }
66 Ok(bits)
67 }
68 _ => bail!("Expected a bit array, found a non-array plaintext."),
69 }
70 }
71}
72
73impl<A: Aleo> Inject for Plaintext<A> {
74 type Primitive = console::Plaintext<A::Network>;
75
76 fn new(mode: Mode, plaintext: Self::Primitive) -> Self {
78 match plaintext {
79 Self::Primitive::Literal(literal, _) => Self::Literal(Literal::new(mode, literal), Default::default()),
80 Self::Primitive::Struct(struct_, _) => Self::Struct(Inject::new(mode, struct_), Default::default()),
81 Self::Primitive::Array(array, _) => Self::Array(Inject::new(mode, array), Default::default()),
82 }
83 }
84}
85
86impl<A: Aleo> Eject for Plaintext<A> {
87 type Primitive = console::Plaintext<A::Network>;
88
89 fn eject_mode(&self) -> Mode {
91 match self {
92 Self::Literal(literal, _) => literal.eject_mode(),
93 Self::Struct(struct_, _) => struct_
94 .iter()
95 .map(|(identifier, value)| (identifier, value).eject_mode())
96 .collect::<Vec<_>>()
97 .eject_mode(),
98 Self::Array(array, _) => array.iter().map(Eject::eject_mode).collect::<Vec<_>>().eject_mode(),
99 }
100 }
101
102 fn eject_value(&self) -> Self::Primitive {
104 match self {
105 Self::Literal(literal, _) => console::Plaintext::Literal(literal.eject_value(), Default::default()),
106 Self::Struct(struct_, _) => {
107 console::Plaintext::Struct(struct_.iter().map(|pair| pair.eject_value()).collect(), Default::default())
108 }
109 Self::Array(array, _) => {
110 console::Plaintext::Array(array.iter().map(Eject::eject_value).collect(), Default::default())
111 }
112 }
113 }
114}
115
116impl<A: Aleo> From<Literal<A>> for Plaintext<A> {
117 fn from(literal: Literal<A>) -> Self {
119 Self::Literal(literal, OnceCell::new())
120 }
121}
122
123impl<A: Aleo> From<&Literal<A>> for Plaintext<A> {
124 fn from(literal: &Literal<A>) -> Self {
126 Self::Literal((*literal).clone(), OnceCell::new())
127 }
128}
129
130macro_rules! impl_plaintext_from_array {
132 ($element:ident, $($size:literal),+) => {
133 $(
134 impl<A: Aleo> From<[$element<A>; $size]> for Plaintext<A> {
135 fn from(value: [$element<A>; $size]) -> Self {
136 Self::Array(
137 value
138 .into_iter()
139 .map(|element| Plaintext::from(Literal::$element(element)))
140 .collect(),
141 OnceCell::new(),
142 )
143 }
144 }
145 )+
146 };
147}
148
149impl_plaintext_from_array!(
151 U8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
152 31, 32
153);
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::Circuit;
159 use snarkvm_utilities::{TestRng, Uniform};
160
161 use anyhow::Result;
162
163 #[test]
164 fn test_plaintext() -> Result<()> {
165 let run_test = |value: Plaintext<Circuit>| {
166 assert_eq!(
167 value.to_bits_le().eject(),
168 Plaintext::<Circuit>::from_bits_le(&value.to_bits_le()).to_bits_le().eject()
169 );
170 assert_eq!(value.eject(), Plaintext::<Circuit>::from_fields(&value.to_fields()).eject());
171 assert!(value.is_equal(&value).eject_value());
172 assert!(!value.is_not_equal(&value).eject_value());
173 };
174
175 let mut rng = TestRng::default();
176
177 run_test(Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()));
179 run_test(Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, false)), OnceCell::new()));
180
181 run_test(Plaintext::<Circuit>::Literal(
183 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
184 OnceCell::new(),
185 ));
186
187 run_test(Plaintext::<Circuit>::Struct(
189 IndexMap::from_iter(vec![
190 (
191 Identifier::new(Mode::Private, "a".try_into()?),
192 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
193 ),
194 (
195 Identifier::new(Mode::Private, "b".try_into()?),
196 Plaintext::<Circuit>::Literal(
197 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
198 OnceCell::new(),
199 ),
200 ),
201 ]),
202 OnceCell::new(),
203 ));
204
205 run_test(Plaintext::<Circuit>::Struct(
207 IndexMap::from_iter(vec![
208 (
209 Identifier::new(Mode::Private, "a".try_into()?),
210 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
211 ),
212 (
213 Identifier::new(Mode::Private, "b".try_into()?),
214 Plaintext::<Circuit>::Array(
215 vec![
216 Plaintext::<Circuit>::Literal(
217 Literal::Boolean(Boolean::new(Mode::Private, true)),
218 OnceCell::new(),
219 ),
220 Plaintext::<Circuit>::Literal(
221 Literal::Boolean(Boolean::new(Mode::Private, false)),
222 OnceCell::new(),
223 ),
224 ],
225 OnceCell::new(),
226 ),
227 ),
228 ]),
229 OnceCell::new(),
230 ));
231
232 run_test(Plaintext::<Circuit>::Struct(
234 IndexMap::from_iter(vec![
235 (
236 Identifier::new(Mode::Private, "a".try_into()?),
237 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
238 ),
239 (
240 Identifier::new(Mode::Private, "b".try_into()?),
241 Plaintext::<Circuit>::Struct(
242 IndexMap::from_iter(vec![
243 (
244 Identifier::new(Mode::Private, "c".try_into()?),
245 Plaintext::<Circuit>::Literal(
246 Literal::Boolean(Boolean::new(Mode::Private, true)),
247 OnceCell::new(),
248 ),
249 ),
250 (
251 Identifier::new(Mode::Private, "d".try_into()?),
252 Plaintext::<Circuit>::Struct(
253 IndexMap::from_iter(vec![
254 (
255 Identifier::new(Mode::Private, "e".try_into()?),
256 Plaintext::<Circuit>::Literal(
257 Literal::Boolean(Boolean::new(Mode::Private, true)),
258 OnceCell::new(),
259 ),
260 ),
261 (
262 Identifier::new(Mode::Private, "f".try_into()?),
263 Plaintext::<Circuit>::Literal(
264 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
265 OnceCell::new(),
266 ),
267 ),
268 ]),
269 OnceCell::new(),
270 ),
271 ),
272 (
273 Identifier::new(Mode::Private, "g".try_into()?),
274 Plaintext::<Circuit>::Array(
275 vec![
276 Plaintext::<Circuit>::Literal(
277 Literal::Boolean(Boolean::new(Mode::Private, true)),
278 OnceCell::new(),
279 ),
280 Plaintext::<Circuit>::Literal(
281 Literal::Boolean(Boolean::new(Mode::Private, false)),
282 OnceCell::new(),
283 ),
284 ],
285 OnceCell::new(),
286 ),
287 ),
288 ]),
289 OnceCell::new(),
290 ),
291 ),
292 (
293 Identifier::new(Mode::Private, "h".try_into()?),
294 Plaintext::<Circuit>::Literal(
295 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
296 OnceCell::new(),
297 ),
298 ),
299 ]),
300 OnceCell::new(),
301 ));
302
303 run_test(Plaintext::<Circuit>::Array(
305 vec![
306 Plaintext::<Circuit>::Literal(
307 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
308 OnceCell::new(),
309 ),
310 Plaintext::<Circuit>::Literal(
311 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
312 OnceCell::new(),
313 ),
314 Plaintext::<Circuit>::Literal(
315 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
316 OnceCell::new(),
317 ),
318 Plaintext::<Circuit>::Literal(
319 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
320 OnceCell::new(),
321 ),
322 Plaintext::<Circuit>::Literal(
323 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
324 OnceCell::new(),
325 ),
326 ],
327 OnceCell::new(),
328 ));
329
330 run_test(Plaintext::<Circuit>::Array(
332 vec![
333 Plaintext::<Circuit>::Struct(
334 IndexMap::from_iter(vec![
335 (
336 Identifier::new(Mode::Private, "x".try_into()?),
337 Plaintext::<Circuit>::Literal(
338 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
339 OnceCell::new(),
340 ),
341 ),
342 (
343 Identifier::new(Mode::Private, "y".try_into()?),
344 Plaintext::<Circuit>::Literal(
345 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
346 OnceCell::new(),
347 ),
348 ),
349 ]),
350 OnceCell::new(),
351 ),
352 Plaintext::<Circuit>::Struct(
353 IndexMap::from_iter(vec![
354 (
355 Identifier::new(Mode::Private, "x".try_into()?),
356 Plaintext::<Circuit>::Literal(
357 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
358 OnceCell::new(),
359 ),
360 ),
361 (
362 Identifier::new(Mode::Private, "y".try_into()?),
363 Plaintext::<Circuit>::Literal(
364 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
365 OnceCell::new(),
366 ),
367 ),
368 ]),
369 OnceCell::new(),
370 ),
371 Plaintext::<Circuit>::Struct(
372 IndexMap::from_iter(vec![
373 (
374 Identifier::new(Mode::Private, "x".try_into()?),
375 Plaintext::<Circuit>::Literal(
376 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
377 OnceCell::new(),
378 ),
379 ),
380 (
381 Identifier::new(Mode::Private, "y".try_into()?),
382 Plaintext::<Circuit>::Literal(
383 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
384 OnceCell::new(),
385 ),
386 ),
387 ]),
388 OnceCell::new(),
389 ),
390 ],
391 OnceCell::new(),
392 ));
393
394 run_test(Plaintext::<Circuit>::Array(
396 vec![
397 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
398 Plaintext::<Circuit>::Literal(
399 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
400 OnceCell::new(),
401 ),
402 Plaintext::<Circuit>::Struct(
403 IndexMap::from_iter(vec![
404 (
405 Identifier::new(Mode::Private, "x".try_into()?),
406 Plaintext::<Circuit>::Literal(
407 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
408 OnceCell::new(),
409 ),
410 ),
411 (
412 Identifier::new(Mode::Private, "y".try_into()?),
413 Plaintext::<Circuit>::Literal(
414 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
415 OnceCell::new(),
416 ),
417 ),
418 ]),
419 OnceCell::new(),
420 ),
421 ],
422 OnceCell::new(),
423 ));
424
425 Ok(())
426 }
427}