1use super::*;
17
18impl<A: Aleo> FromBits for Plaintext<A> {
19 type Boolean = Boolean<A>;
20
21 fn from_bits_le(bits_le: &[Boolean<A>]) -> Self {
23 Self::from_bits_le_internal(bits_le, 0)
24 }
25
26 fn from_bits_be(bits_be: &[Boolean<A>]) -> Self {
28 Self::from_bits_be_internal(bits_be, 0)
29 }
30}
31
32impl<A: Aleo> Plaintext<A> {
33 fn from_bits_le_internal(bits_le: &[Boolean<A>], depth: usize) -> Self {
35 if depth > <A::Network as console::Network>::MAX_DATA_DEPTH {
37 A::halt(format!(
38 "Plaintext depth exceeds maximum limit: {}",
39 <A::Network as console::Network>::MAX_DATA_DEPTH
40 ))
41 }
42
43 let bits = bits_le;
44
45 let mut index = 0;
47
48 let mut next_bits = |n: usize| -> &[Boolean<A>] {
50 let subslice = bits.get(index..index + n);
52 if let Some(next_bits) = subslice {
54 index += n;
56 next_bits
58 } else {
59 A::halt("Insufficient bits.")
60 }
61 };
62
63 let mut variant = next_bits(2).iter().map(|b| b.eject_value());
64 let variant1 = variant.next().unwrap();
65 let variant2 = variant.next().unwrap();
66 let variant = [variant1, variant2];
67
68 if variant == [false, false] {
70 let literal_variant = U8::from_bits_le(next_bits(8));
71 let literal_size = U16::from_bits_le(next_bits(16)).eject_value();
72 let literal = Literal::from_bits_le(&literal_variant, next_bits(*literal_size as usize));
73
74 let cell = OnceCell::new();
76 cell.set(bits_le.to_vec()).unwrap();
77 Self::Literal(literal, cell)
78 }
79 else if variant == [false, true] {
81 let num_members = U8::from_bits_le(next_bits(8)).eject_value();
82
83 let mut members = IndexMap::with_capacity(*num_members as usize);
84 for _ in 0..*num_members {
85 let identifier_size = U8::from_bits_le(next_bits(8)).eject_value();
86 let identifier = Identifier::from_bits_le(next_bits(*identifier_size as usize));
87
88 let member_size = U16::from_bits_le(next_bits(16)).eject_value();
89 let value = Plaintext::from_bits_le_internal(next_bits(*member_size as usize), depth + 1);
90
91 members.insert(identifier, value);
92 }
93
94 let cell = OnceCell::new();
96 cell.set(bits_le.to_vec()).unwrap();
97 Self::Struct(members, cell)
98 }
99 else if variant == [true, false] {
101 let num_elements = U32::from_bits_le(next_bits(32)).eject_value();
102
103 let mut elements = Vec::with_capacity(*num_elements as usize);
104 for _ in 0..*num_elements {
105 let element_size = U16::from_bits_le(next_bits(16)).eject_value();
106 let value = Plaintext::from_bits_le_internal(next_bits(*element_size as usize), depth + 1);
107
108 elements.push(value);
109 }
110
111 let cell = OnceCell::new();
113 cell.set(bits_le.to_vec()).unwrap();
114 Self::Array(elements, cell)
115 }
116 else {
118 A::halt("Unknown plaintext variant.")
119 }
120 }
121
122 fn from_bits_be_internal(bits_be: &[Boolean<A>], depth: usize) -> Self {
124 if depth > <A::Network as console::Network>::MAX_DATA_DEPTH {
126 A::halt(format!(
127 "Plaintext depth exceeds maximum limit: {}",
128 <A::Network as console::Network>::MAX_DATA_DEPTH
129 ))
130 }
131
132 let bits = bits_be;
133
134 let mut index = 0;
136
137 let mut next_bits = |n: usize| -> &[Boolean<A>] {
139 let subslice = bits.get(index..index + n);
141 if let Some(next_bits) = subslice {
143 index += n;
145 next_bits
147 } else {
148 A::halt("Insufficient bits.")
149 }
150 };
151
152 let mut variant = next_bits(2).iter().map(|b| b.eject_value());
153 let variant1 = variant.next().unwrap();
154 let variant2 = variant.next().unwrap();
155 let variant = [variant1, variant2];
156
157 if variant == [false, false] {
159 let literal_variant = U8::from_bits_be(next_bits(8));
160 let literal_size = U16::from_bits_be(next_bits(16)).eject_value();
161 let literal = Literal::from_bits_be(&literal_variant, next_bits(*literal_size as usize));
162
163 let cell = OnceCell::new();
165 cell.set(bits_be.to_vec()).unwrap();
166 Self::Literal(literal, cell)
167 }
168 else if variant == [false, true] {
170 let num_members = U8::from_bits_be(next_bits(8)).eject_value();
171
172 let mut members = IndexMap::with_capacity(*num_members as usize);
173 for _ in 0..*num_members {
174 let identifier_size = U8::from_bits_be(next_bits(8)).eject_value();
175 let identifier = Identifier::from_bits_be(next_bits(*identifier_size as usize));
176
177 let member_size = U16::from_bits_be(next_bits(16)).eject_value();
178 let value = Plaintext::from_bits_be_internal(next_bits(*member_size as usize), depth + 1);
179
180 members.insert(identifier, value);
181 }
182
183 let cell = OnceCell::new();
185 cell.set(bits_be.to_vec()).unwrap();
186 Self::Struct(members, cell)
187 }
188 else if variant == [true, false] {
190 let num_elements = U32::from_bits_be(next_bits(32)).eject_value();
191
192 let mut elements = Vec::with_capacity(*num_elements as usize);
193 for _ in 0..*num_elements {
194 let element_size = U16::from_bits_be(next_bits(16)).eject_value();
195 let value = Plaintext::from_bits_be_internal(next_bits(*element_size as usize), depth + 1);
196
197 elements.push(value);
198 }
199
200 let cell = OnceCell::new();
202 cell.set(bits_be.to_vec()).unwrap();
203 Self::Array(elements, cell)
204 }
205 else {
207 A::halt("Unknown plaintext variant.")
208 }
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215 use console_root::network::{MainnetV0, Network};
216 use snarkvm_circuit_network::AleoV0;
217
218 type CurrentAleo = AleoV0;
219 type CurrentNetwork = MainnetV0;
220
221 fn get_depth(plaintext: &Plaintext<CurrentAleo>) -> usize {
223 match plaintext {
224 Plaintext::Literal(_, _) => 0,
225 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1,
226 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1,
227 }
228 }
229
230 #[test]
231 fn test_deeply_nested_plaintext_bits_le() {
232 fn create_nested_array(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
234 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
236 result.reverse();
238 for _ in 0..depth {
240 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
242 length.reverse();
243 result.extend(length);
244 let mut num_elements = 1u32.to_bits_le();
246 num_elements.reverse();
247 result.extend(num_elements);
248 result.extend([false, true]);
250 }
251 result.reverse();
253 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
255 result
256 }
257
258 fn create_nested_struct(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
260 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
262 result.reverse();
264 for _ in 0..depth {
266 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
268 length.reverse();
269 result.extend(length);
270 let mut member_name = console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le();
272 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le();
273 member_name.reverse();
274 result.extend(member_name);
275 member_name_length.reverse();
277 result.extend(member_name_length);
278 let mut num_members = 1u8.to_bits_le();
280 num_members.reverse();
281 result.extend(num_members);
282 result.extend([true, false]);
284 }
285 result.reverse();
287 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
289 result
290 }
291
292 fn create_alternated_nested(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
294 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
296 result.reverse();
298 for i in 0..depth {
300 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
302 length.reverse();
303 result.extend(length);
304 if i % 2 == 0 {
306 let mut num_elements = 1u32.to_bits_le();
308 num_elements.reverse();
309 result.extend(num_elements);
310 result.extend([false, true]);
312 } else {
313 let mut member_name =
315 console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le();
316 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le();
317 member_name.reverse();
318 result.extend(member_name);
319 member_name_length.reverse();
321 result.extend(member_name_length);
322 let mut num_members = 1u8.to_bits_le();
324 num_members.reverse();
325 result.extend(num_members);
326 result.extend([true, false]);
328 }
329 }
330 result.reverse();
332 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
334 result
335 }
336
337 fn run_test(expected_depth: usize, input: Vec<Boolean<CurrentAleo>>, expected_error: bool) {
339 let result = std::panic::catch_unwind(|| Plaintext::<CurrentAleo>::from_bits_le(&input));
341 CurrentAleo::reset();
342 match expected_error {
344 true => {
345 assert!(result.is_err());
346 return;
347 }
348 false => assert!(result.is_ok()),
349 };
350 let candidate = result.unwrap();
352 for (i, expected_bit) in input.iter().enumerate() {
354 assert_eq!(expected_bit.eject_value(), candidate.to_bits_le()[i].eject_value());
355 }
356 assert_eq!(get_depth(&candidate), expected_depth);
358 }
359
360 let mut depths = (0usize..100).collect_vec();
363 depths.extend((100..890).step_by(10));
364
365 for i in depths.iter().copied() {
367 run_test(i, create_nested_array(Mode::Constant, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
368 run_test(i, create_nested_array(Mode::Public, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
369 run_test(i, create_nested_array(Mode::Private, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
370 run_test(i, create_nested_array(Mode::Constant, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
371 }
372
373 for i in depths.iter().copied() {
375 run_test(i, create_nested_struct(Mode::Public, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
376 run_test(i, create_nested_struct(Mode::Private, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
377 run_test(i, create_nested_struct(Mode::Constant, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
378 run_test(i, create_nested_struct(Mode::Public, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
379 }
380
381 for i in depths.iter().copied() {
383 run_test(i, create_alternated_nested(Mode::Private, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
384 run_test(i, create_alternated_nested(Mode::Constant, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
385 run_test(i, create_alternated_nested(Mode::Public, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
386 run_test(i, create_alternated_nested(Mode::Private, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
387 }
388 }
389
390 #[test]
391 fn test_deeply_nested_plaintext_bits_be() {
392 fn create_nested_array(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
394 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
396 result.reverse();
398 for _ in 0..depth {
400 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
402 length.reverse();
403 result.extend(length);
404 let mut num_elements = 1u32.to_bits_be();
406 num_elements.reverse();
407 result.extend(num_elements);
408 result.extend([false, true]);
410 }
411 result.reverse();
413 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
415 result
416 }
417
418 fn create_nested_struct(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
420 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
422 result.reverse();
424 for _ in 0..depth {
426 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
428 length.reverse();
429 result.extend(length);
430 let mut member_name = console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
432 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
433 member_name.reverse();
434 result.extend(member_name);
435 member_name_length.reverse();
437 result.extend(member_name_length);
438 let mut num_members = 1u8.to_bits_be();
440 num_members.reverse();
441 result.extend(num_members);
442 result.extend([true, false]);
444 }
445 result.reverse();
447 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
449 result
450 }
451
452 fn create_alternated_nested(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
454 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
456 result.reverse();
458 for i in 0..depth {
460 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
462 length.reverse();
463 result.extend(length);
464 if i % 2 == 0 {
466 let mut num_elements = 1u32.to_bits_be();
468 num_elements.reverse();
469 result.extend(num_elements);
470 result.extend([false, true]);
472 } else {
473 let mut member_name =
475 console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
476 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
477 member_name.reverse();
478 result.extend(member_name);
479 member_name_length.reverse();
481 result.extend(member_name_length);
482 let mut num_members = 1u8.to_bits_be();
484 num_members.reverse();
485 result.extend(num_members);
486 result.extend([true, false]);
488 }
489 }
490 result.reverse();
492 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
494 result
495 }
496
497 fn run_test(expected_depth: usize, input: Vec<Boolean<CurrentAleo>>, expected_error: bool) {
499 let result = std::panic::catch_unwind(|| Plaintext::<CurrentAleo>::from_bits_be(&input));
501 CurrentAleo::reset();
502 match expected_error {
504 true => {
505 assert!(result.is_err());
506 return;
507 }
508 false => assert!(result.is_ok()),
509 };
510 let candidate = result.unwrap();
512 for (i, expected_bit) in input.iter().enumerate() {
514 assert_eq!(expected_bit.eject_value(), candidate.to_bits_be()[i].eject_value());
515 }
516 assert_eq!(get_depth(&candidate), expected_depth);
518 }
519
520 let mut depths = (0usize..100).collect_vec();
523 depths.extend((100..890).step_by(10));
524
525 for i in depths.iter().copied() {
527 run_test(i, create_nested_array(Mode::Constant, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
528 run_test(i, create_nested_array(Mode::Public, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
529 run_test(i, create_nested_array(Mode::Private, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
530 run_test(i, create_nested_array(Mode::Constant, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
531 }
532
533 for i in depths.iter().copied() {
535 run_test(i, create_nested_struct(Mode::Public, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
536 run_test(i, create_nested_struct(Mode::Private, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
537 run_test(i, create_nested_struct(Mode::Constant, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
538 run_test(i, create_nested_struct(Mode::Public, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
539 }
540
541 for i in depths.iter().copied() {
543 run_test(i, create_alternated_nested(Mode::Private, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
544 run_test(i, create_alternated_nested(Mode::Constant, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
545 run_test(i, create_alternated_nested(Mode::Public, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
546 run_test(i, create_alternated_nested(Mode::Private, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
547 }
548 }
549}