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 Self::Literal(literal, OnceCell::with_value(bits_le.to_vec()))
76 }
77 else if variant == [false, true] {
79 let num_members = U8::from_bits_le(next_bits(8)).eject_value();
80
81 let mut members = IndexMap::with_capacity(*num_members as usize);
82 for _ in 0..*num_members {
83 let identifier_size = U8::from_bits_le(next_bits(8)).eject_value();
84 let identifier = Identifier::from_bits_le(next_bits(*identifier_size as usize));
85
86 let member_size = U16::from_bits_le(next_bits(16)).eject_value();
87 let value = Plaintext::from_bits_le_internal(next_bits(*member_size as usize), depth + 1);
88
89 members.insert(identifier, value);
90 }
91
92 Self::Struct(members, OnceCell::with_value(bits_le.to_vec()))
94 }
95 else if variant == [true, false] {
97 let num_elements = U32::from_bits_le(next_bits(32)).eject_value();
98
99 let mut elements = Vec::with_capacity(*num_elements as usize);
100 for _ in 0..*num_elements {
101 let element_size = U16::from_bits_le(next_bits(16)).eject_value();
102 let value = Plaintext::from_bits_le_internal(next_bits(*element_size as usize), depth + 1);
103
104 elements.push(value);
105 }
106
107 Self::Array(elements, OnceCell::with_value(bits_le.to_vec()))
109 }
110 else {
112 A::halt("Unknown plaintext variant.")
113 }
114 }
115
116 fn from_bits_be_internal(bits_be: &[Boolean<A>], depth: usize) -> Self {
118 if depth > <A::Network as console::Network>::MAX_DATA_DEPTH {
120 A::halt(format!(
121 "Plaintext depth exceeds maximum limit: {}",
122 <A::Network as console::Network>::MAX_DATA_DEPTH
123 ))
124 }
125
126 let bits = bits_be;
127
128 let mut index = 0;
130
131 let mut next_bits = |n: usize| -> &[Boolean<A>] {
133 let subslice = bits.get(index..index + n);
135 if let Some(next_bits) = subslice {
137 index += n;
139 next_bits
141 } else {
142 A::halt("Insufficient bits.")
143 }
144 };
145
146 let mut variant = next_bits(2).iter().map(|b| b.eject_value());
147 let variant1 = variant.next().unwrap();
148 let variant2 = variant.next().unwrap();
149 let variant = [variant1, variant2];
150
151 if variant == [false, false] {
153 let literal_variant = U8::from_bits_be(next_bits(8));
154 let literal_size = U16::from_bits_be(next_bits(16)).eject_value();
155 let literal = Literal::from_bits_be(&literal_variant, next_bits(*literal_size as usize));
156
157 Self::Literal(literal, OnceCell::with_value(bits_be.to_vec()))
159 }
160 else if variant == [false, true] {
162 let num_members = U8::from_bits_be(next_bits(8)).eject_value();
163
164 let mut members = IndexMap::with_capacity(*num_members as usize);
165 for _ in 0..*num_members {
166 let identifier_size = U8::from_bits_be(next_bits(8)).eject_value();
167 let identifier = Identifier::from_bits_be(next_bits(*identifier_size as usize));
168
169 let member_size = U16::from_bits_be(next_bits(16)).eject_value();
170 let value = Plaintext::from_bits_be_internal(next_bits(*member_size as usize), depth + 1);
171
172 members.insert(identifier, value);
173 }
174
175 Self::Struct(members, OnceCell::with_value(bits_be.to_vec()))
177 }
178 else if variant == [true, false] {
180 let num_elements = U32::from_bits_be(next_bits(32)).eject_value();
181
182 let mut elements = Vec::with_capacity(*num_elements as usize);
183 for _ in 0..*num_elements {
184 let element_size = U16::from_bits_be(next_bits(16)).eject_value();
185 let value = Plaintext::from_bits_be_internal(next_bits(*element_size as usize), depth + 1);
186
187 elements.push(value);
188 }
189
190 Self::Array(elements, OnceCell::with_value(bits_be.to_vec()))
192 }
193 else {
195 A::halt("Unknown plaintext variant.")
196 }
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203 use console_root::network::{MainnetV0, Network};
204 use snarkvm_circuit_network::AleoV0;
205
206 type CurrentAleo = AleoV0;
207 type CurrentNetwork = MainnetV0;
208
209 fn get_depth(plaintext: &Plaintext<CurrentAleo>) -> usize {
211 match plaintext {
212 Plaintext::Literal(_, _) => 0,
213 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1,
214 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1,
215 }
216 }
217
218 #[test]
219 fn test_deeply_nested_plaintext_bits_le() {
220 fn create_nested_array(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
222 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
224 result.reverse();
226 for _ in 0..depth {
228 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
230 length.reverse();
231 result.extend(length);
232 let mut num_elements = 1u32.to_bits_le();
234 num_elements.reverse();
235 result.extend(num_elements);
236 result.extend([false, true]);
238 }
239 result.reverse();
241 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
243 result
244 }
245
246 fn create_nested_struct(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
248 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
250 result.reverse();
252 for _ in 0..depth {
254 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
256 length.reverse();
257 result.extend(length);
258 let mut member_name = console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le();
260 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le();
261 member_name.reverse();
262 result.extend(member_name);
263 member_name_length.reverse();
265 result.extend(member_name_length);
266 let mut num_members = 1u8.to_bits_le();
268 num_members.reverse();
269 result.extend(num_members);
270 result.extend([true, false]);
272 }
273 result.reverse();
275 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
277 result
278 }
279
280 fn create_alternated_nested(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
282 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
284 result.reverse();
286 for i in 0..depth {
288 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
290 length.reverse();
291 result.extend(length);
292 if i % 2 == 0 {
294 let mut num_elements = 1u32.to_bits_le();
296 num_elements.reverse();
297 result.extend(num_elements);
298 result.extend([false, true]);
300 } else {
301 let mut member_name =
303 console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le();
304 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le();
305 member_name.reverse();
306 result.extend(member_name);
307 member_name_length.reverse();
309 result.extend(member_name_length);
310 let mut num_members = 1u8.to_bits_le();
312 num_members.reverse();
313 result.extend(num_members);
314 result.extend([true, false]);
316 }
317 }
318 result.reverse();
320 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
322 result
323 }
324
325 fn run_test(expected_depth: usize, input: Vec<Boolean<CurrentAleo>>, expected_error: bool) {
327 let result = std::panic::catch_unwind(|| Plaintext::<CurrentAleo>::from_bits_le(&input));
329 CurrentAleo::reset();
330 match expected_error {
332 true => {
333 assert!(result.is_err());
334 return;
335 }
336 false => assert!(result.is_ok()),
337 };
338 let candidate = result.unwrap();
340 for (i, expected_bit) in input.iter().enumerate() {
342 assert_eq!(expected_bit.eject_value(), candidate.to_bits_le()[i].eject_value());
343 }
344 assert_eq!(get_depth(&candidate), expected_depth);
346 }
347
348 let mut depths = (0usize..100).collect_vec();
351 depths.extend((100..890).step_by(10));
352
353 for i in depths.iter().copied() {
355 run_test(i, create_nested_array(Mode::Constant, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
356 run_test(i, create_nested_array(Mode::Public, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
357 run_test(i, create_nested_array(Mode::Private, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
358 run_test(i, create_nested_array(Mode::Constant, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
359 }
360
361 for i in depths.iter().copied() {
363 run_test(i, create_nested_struct(Mode::Public, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
364 run_test(i, create_nested_struct(Mode::Private, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
365 run_test(i, create_nested_struct(Mode::Constant, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
366 run_test(i, create_nested_struct(Mode::Public, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
367 }
368
369 for i in depths.iter().copied() {
371 run_test(i, create_alternated_nested(Mode::Private, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
372 run_test(i, create_alternated_nested(Mode::Constant, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
373 run_test(i, create_alternated_nested(Mode::Public, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
374 run_test(i, create_alternated_nested(Mode::Private, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
375 }
376 }
377
378 #[test]
379 fn test_deeply_nested_plaintext_bits_be() {
380 fn create_nested_array(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
382 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
384 result.reverse();
386 for _ in 0..depth {
388 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
390 length.reverse();
391 result.extend(length);
392 let mut num_elements = 1u32.to_bits_be();
394 num_elements.reverse();
395 result.extend(num_elements);
396 result.extend([false, true]);
398 }
399 result.reverse();
401 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
403 result
404 }
405
406 fn create_nested_struct(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
408 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
410 result.reverse();
412 for _ in 0..depth {
414 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
416 length.reverse();
417 result.extend(length);
418 let mut member_name = console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
420 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
421 member_name.reverse();
422 result.extend(member_name);
423 member_name_length.reverse();
425 result.extend(member_name_length);
426 let mut num_members = 1u8.to_bits_be();
428 num_members.reverse();
429 result.extend(num_members);
430 result.extend([true, false]);
432 }
433 result.reverse();
435 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
437 result
438 }
439
440 fn create_alternated_nested(mode: Mode, depth: usize, root: impl Display) -> Vec<Boolean<CurrentAleo>> {
442 let mut result = console::Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
444 result.reverse();
446 for i in 0..depth {
448 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
450 length.reverse();
451 result.extend(length);
452 if i % 2 == 0 {
454 let mut num_elements = 1u32.to_bits_be();
456 num_elements.reverse();
457 result.extend(num_elements);
458 result.extend([false, true]);
460 } else {
461 let mut member_name =
463 console::Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
464 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
465 member_name.reverse();
466 result.extend(member_name);
467 member_name_length.reverse();
469 result.extend(member_name_length);
470 let mut num_members = 1u8.to_bits_be();
472 num_members.reverse();
473 result.extend(num_members);
474 result.extend([true, false]);
476 }
477 }
478 result.reverse();
480 let result: Vec<Boolean<CurrentAleo>> = result.into_iter().map(|input| Boolean::new(mode, input)).collect();
482 result
483 }
484
485 fn run_test(expected_depth: usize, input: Vec<Boolean<CurrentAleo>>, expected_error: bool) {
487 let result = std::panic::catch_unwind(|| Plaintext::<CurrentAleo>::from_bits_be(&input));
489 CurrentAleo::reset();
490 match expected_error {
492 true => {
493 assert!(result.is_err());
494 return;
495 }
496 false => assert!(result.is_ok()),
497 };
498 let candidate = result.unwrap();
500 for (i, expected_bit) in input.iter().enumerate() {
502 assert_eq!(expected_bit.eject_value(), candidate.to_bits_be()[i].eject_value());
503 }
504 assert_eq!(get_depth(&candidate), expected_depth);
506 }
507
508 let mut depths = (0usize..100).collect_vec();
511 depths.extend((100..890).step_by(10));
512
513 for i in depths.iter().copied() {
515 run_test(i, create_nested_array(Mode::Constant, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
516 run_test(i, create_nested_array(Mode::Public, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
517 run_test(i, create_nested_array(Mode::Private, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
518 run_test(i, create_nested_array(Mode::Constant, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
519 }
520
521 for i in depths.iter().copied() {
523 run_test(i, create_nested_struct(Mode::Public, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
524 run_test(i, create_nested_struct(Mode::Private, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
525 run_test(i, create_nested_struct(Mode::Constant, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
526 run_test(i, create_nested_struct(Mode::Public, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
527 }
528
529 for i in depths.iter().copied() {
531 run_test(i, create_alternated_nested(Mode::Private, i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
532 run_test(i, create_alternated_nested(Mode::Constant, i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
533 run_test(i, create_alternated_nested(Mode::Public, i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
534 run_test(i, create_alternated_nested(Mode::Private, i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
535 }
536 }
537}