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(
81 struct_
82 .into_iter()
83 .map(|(identifier, member)| (Identifier::constant(identifier), Inject::new(mode, member)))
84 .collect(),
85 Default::default(),
86 ),
87 Self::Primitive::Array(array, _) => Self::Array(Inject::new(mode, array), Default::default()),
88 }
89 }
90}
91
92impl<A: Aleo> Eject for Plaintext<A> {
93 type Primitive = console::Plaintext<A::Network>;
94
95 fn eject_mode(&self) -> Mode {
97 match self {
98 Self::Literal(literal, _) => literal.eject_mode(),
99 Self::Struct(struct_, _) => struct_
100 .iter()
101 .map(|(identifier, value)| (identifier, value).eject_mode())
102 .collect::<Vec<_>>()
103 .eject_mode(),
104 Self::Array(array, _) => array.iter().map(Eject::eject_mode).collect::<Vec<_>>().eject_mode(),
105 }
106 }
107
108 fn eject_value(&self) -> Self::Primitive {
110 match self {
111 Self::Literal(literal, _) => console::Plaintext::Literal(literal.eject_value(), Default::default()),
112 Self::Struct(struct_, _) => {
113 console::Plaintext::Struct(struct_.iter().map(|pair| pair.eject_value()).collect(), Default::default())
114 }
115 Self::Array(array, _) => {
116 console::Plaintext::Array(array.iter().map(Eject::eject_value).collect(), Default::default())
117 }
118 }
119 }
120}
121
122impl<A: Aleo> From<Literal<A>> for Plaintext<A> {
123 fn from(literal: Literal<A>) -> Self {
125 Self::Literal(literal, OnceCell::new())
126 }
127}
128
129impl<A: Aleo> From<&Literal<A>> for Plaintext<A> {
130 fn from(literal: &Literal<A>) -> Self {
132 Self::Literal((*literal).clone(), OnceCell::new())
133 }
134}
135
136macro_rules! impl_plaintext_from_array {
138 ($element:ident, $($size:literal),+) => {
139 $(
140 impl<A: Aleo> From<[$element<A>; $size]> for Plaintext<A> {
141 fn from(value: [$element<A>; $size]) -> Self {
142 Self::Array(
143 value
144 .into_iter()
145 .map(|element| Plaintext::from(Literal::$element(element)))
146 .collect(),
147 OnceCell::new(),
148 )
149 }
150 }
151 )+
152 };
153}
154
155impl_plaintext_from_array!(
157 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,
158 31, 32
159);
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164 use crate::Circuit;
165 use snarkvm_utilities::{TestRng, Uniform};
166
167 use anyhow::Result;
168
169 #[test]
170 fn test_plaintext() -> Result<()> {
171 let run_test = |value: Plaintext<Circuit>| {
172 assert_eq!(
173 value.to_bits_le().eject(),
174 Plaintext::<Circuit>::from_bits_le(&value.to_bits_le()).to_bits_le().eject()
175 );
176 assert_eq!(value.eject(), Plaintext::<Circuit>::from_fields(&value.to_fields()).eject());
177 assert!(value.is_equal(&value).eject_value());
178 assert!(!value.is_not_equal(&value).eject_value());
179 };
180
181 let mut rng = TestRng::default();
182
183 run_test(Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()));
185 run_test(Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, false)), OnceCell::new()));
186
187 run_test(Plaintext::<Circuit>::Literal(
189 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
190 OnceCell::new(),
191 ));
192
193 run_test(Plaintext::<Circuit>::Struct(
195 IndexMap::from_iter(vec![
196 (
197 Identifier::constant("a".try_into()?),
198 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
199 ),
200 (
201 Identifier::constant("b".try_into()?),
202 Plaintext::<Circuit>::Literal(
203 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
204 OnceCell::new(),
205 ),
206 ),
207 ]),
208 OnceCell::new(),
209 ));
210
211 run_test(Plaintext::<Circuit>::Struct(
213 IndexMap::from_iter(vec![
214 (
215 Identifier::constant("a".try_into()?),
216 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
217 ),
218 (
219 Identifier::constant("b".try_into()?),
220 Plaintext::<Circuit>::Array(
221 vec![
222 Plaintext::<Circuit>::Literal(
223 Literal::Boolean(Boolean::new(Mode::Private, true)),
224 OnceCell::new(),
225 ),
226 Plaintext::<Circuit>::Literal(
227 Literal::Boolean(Boolean::new(Mode::Private, false)),
228 OnceCell::new(),
229 ),
230 ],
231 OnceCell::new(),
232 ),
233 ),
234 ]),
235 OnceCell::new(),
236 ));
237
238 run_test(Plaintext::<Circuit>::Struct(
240 IndexMap::from_iter(vec![
241 (
242 Identifier::constant("a".try_into()?),
243 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
244 ),
245 (
246 Identifier::constant("b".try_into()?),
247 Plaintext::<Circuit>::Struct(
248 IndexMap::from_iter(vec![
249 (
250 Identifier::constant("c".try_into()?),
251 Plaintext::<Circuit>::Literal(
252 Literal::Boolean(Boolean::new(Mode::Private, true)),
253 OnceCell::new(),
254 ),
255 ),
256 (
257 Identifier::constant("d".try_into()?),
258 Plaintext::<Circuit>::Struct(
259 IndexMap::from_iter(vec![
260 (
261 Identifier::constant("e".try_into()?),
262 Plaintext::<Circuit>::Literal(
263 Literal::Boolean(Boolean::new(Mode::Private, true)),
264 OnceCell::new(),
265 ),
266 ),
267 (
268 Identifier::constant("f".try_into()?),
269 Plaintext::<Circuit>::Literal(
270 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
271 OnceCell::new(),
272 ),
273 ),
274 ]),
275 OnceCell::new(),
276 ),
277 ),
278 (
279 Identifier::constant("g".try_into()?),
280 Plaintext::<Circuit>::Array(
281 vec![
282 Plaintext::<Circuit>::Literal(
283 Literal::Boolean(Boolean::new(Mode::Private, true)),
284 OnceCell::new(),
285 ),
286 Plaintext::<Circuit>::Literal(
287 Literal::Boolean(Boolean::new(Mode::Private, false)),
288 OnceCell::new(),
289 ),
290 ],
291 OnceCell::new(),
292 ),
293 ),
294 ]),
295 OnceCell::new(),
296 ),
297 ),
298 (
299 Identifier::constant("h".try_into()?),
300 Plaintext::<Circuit>::Literal(
301 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
302 OnceCell::new(),
303 ),
304 ),
305 ]),
306 OnceCell::new(),
307 ));
308
309 run_test(Plaintext::<Circuit>::Array(
311 vec![
312 Plaintext::<Circuit>::Literal(
313 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
314 OnceCell::new(),
315 ),
316 Plaintext::<Circuit>::Literal(
317 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
318 OnceCell::new(),
319 ),
320 Plaintext::<Circuit>::Literal(
321 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
322 OnceCell::new(),
323 ),
324 Plaintext::<Circuit>::Literal(
325 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
326 OnceCell::new(),
327 ),
328 Plaintext::<Circuit>::Literal(
329 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
330 OnceCell::new(),
331 ),
332 ],
333 OnceCell::new(),
334 ));
335
336 run_test(Plaintext::<Circuit>::Array(
338 vec![
339 Plaintext::<Circuit>::Struct(
340 IndexMap::from_iter(vec![
341 (
342 Identifier::constant("x".try_into()?),
343 Plaintext::<Circuit>::Literal(
344 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
345 OnceCell::new(),
346 ),
347 ),
348 (
349 Identifier::constant("y".try_into()?),
350 Plaintext::<Circuit>::Literal(
351 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
352 OnceCell::new(),
353 ),
354 ),
355 ]),
356 OnceCell::new(),
357 ),
358 Plaintext::<Circuit>::Struct(
359 IndexMap::from_iter(vec![
360 (
361 Identifier::constant("x".try_into()?),
362 Plaintext::<Circuit>::Literal(
363 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
364 OnceCell::new(),
365 ),
366 ),
367 (
368 Identifier::constant("y".try_into()?),
369 Plaintext::<Circuit>::Literal(
370 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
371 OnceCell::new(),
372 ),
373 ),
374 ]),
375 OnceCell::new(),
376 ),
377 Plaintext::<Circuit>::Struct(
378 IndexMap::from_iter(vec![
379 (
380 Identifier::constant("x".try_into()?),
381 Plaintext::<Circuit>::Literal(
382 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
383 OnceCell::new(),
384 ),
385 ),
386 (
387 Identifier::constant("y".try_into()?),
388 Plaintext::<Circuit>::Literal(
389 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
390 OnceCell::new(),
391 ),
392 ),
393 ]),
394 OnceCell::new(),
395 ),
396 ],
397 OnceCell::new(),
398 ));
399
400 run_test(Plaintext::<Circuit>::Array(
402 vec![
403 Plaintext::<Circuit>::Literal(Literal::Boolean(Boolean::new(Mode::Private, true)), OnceCell::new()),
404 Plaintext::<Circuit>::Literal(
405 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
406 OnceCell::new(),
407 ),
408 Plaintext::<Circuit>::Struct(
409 IndexMap::from_iter(vec![
410 (
411 Identifier::constant("x".try_into()?),
412 Plaintext::<Circuit>::Literal(
413 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
414 OnceCell::new(),
415 ),
416 ),
417 (
418 Identifier::constant("y".try_into()?),
419 Plaintext::<Circuit>::Literal(
420 Literal::Field(Field::new(Mode::Private, Uniform::rand(&mut rng))),
421 OnceCell::new(),
422 ),
423 ),
424 ]),
425 OnceCell::new(),
426 ),
427 ],
428 OnceCell::new(),
429 ));
430
431 Ok(())
432 }
433}