snarkvm_console_program/data/plaintext/
from_bits.rs1use super::*;
17
18impl<N: Network> FromBits for Plaintext<N> {
19 fn from_bits_le(bits_le: &[bool]) -> Result<Self> {
21 Self::from_bits_le_internal(bits_le, 0)
22 }
23
24 fn from_bits_be(bits_be: &[bool]) -> Result<Self> {
26 Self::from_bits_be_internal(bits_be, 0)
27 }
28}
29
30impl<N: Network> Plaintext<N> {
31 fn from_bits_le_internal(bits_le: &[bool], depth: usize) -> Result<Self> {
33 if depth > N::MAX_DATA_DEPTH {
35 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
36 }
37
38 let bits = bits_le;
39
40 let mut index = 0;
42
43 let mut next_bits = |n: usize| -> Result<&[bool]> {
45 let subslice = bits.get(index..index + n);
47 if let Some(next_bits) = subslice {
49 index += n;
51 Ok(next_bits)
53 } else {
54 bail!("Insufficient bits");
55 }
56 };
57
58 let variant = next_bits(2)?;
59 let variant = [variant[0], variant[1]];
60
61 if variant == [false, false] {
63 let literal_variant = u8::from_bits_le(next_bits(8)?)?;
64 let literal_size = u16::from_bits_le(next_bits(16)?)?;
65 let literal = Literal::from_bits_le(literal_variant, next_bits(literal_size as usize)?)?;
66
67 Ok(Self::Literal(literal, OnceCell::with_value(bits_le.to_vec())))
69 }
70 else if variant == [false, true] {
72 let num_members = u8::from_bits_le(next_bits(8)?)?;
73 if num_members as usize > N::MAX_STRUCT_ENTRIES {
74 bail!("Struct exceeds maximum of entries.");
75 }
76
77 let mut members = IndexMap::with_capacity(num_members as usize);
78 for _ in 0..num_members {
79 let identifier_size = u8::from_bits_le(next_bits(8)?)?;
80 let identifier = Identifier::from_bits_le(next_bits(identifier_size as usize)?)?;
81
82 let member_size = u16::from_bits_le(next_bits(16)?)?;
83 let value = Plaintext::from_bits_le_internal(next_bits(member_size as usize)?, depth + 1)?;
84
85 if members.insert(identifier, value).is_some() {
86 bail!("Duplicate identifier in struct.");
87 }
88 }
89
90 Ok(Self::Struct(members, OnceCell::with_value(bits_le.to_vec())))
92 }
93 else if variant == [true, false] {
95 let num_elements = u32::from_bits_le(next_bits(32)?)?;
96 if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
97 bail!("Array exceeds maximum of elements.");
98 }
99
100 let mut elements = Vec::with_capacity(num_elements as usize);
101 for _ in 0..num_elements {
102 let element_size = u16::from_bits_le(next_bits(16)?)?;
103 let element = Plaintext::from_bits_le_internal(next_bits(element_size as usize)?, depth + 1)?;
104
105 elements.push(element);
106 }
107
108 Ok(Self::Array(elements, OnceCell::with_value(bits_le.to_vec())))
110 }
111 else {
113 bail!("Unknown plaintext variant - {variant:?}");
114 }
115 }
116
117 fn from_bits_be_internal(bits_be: &[bool], depth: usize) -> Result<Self> {
119 if depth > N::MAX_DATA_DEPTH {
121 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
122 }
123
124 let bits = bits_be;
125
126 let mut index = 0;
128
129 let mut next_bits = |n: usize| -> Result<&[bool]> {
131 let subslice = bits.get(index..index + n);
133 if let Some(next_bits) = subslice {
135 index += n;
137 Ok(next_bits)
139 } else {
140 bail!("Insufficient bits");
141 }
142 };
143
144 let variant = next_bits(2)?;
145 let variant = [variant[0], variant[1]];
146
147 if variant == [false, false] {
149 let literal_variant = u8::from_bits_be(next_bits(8)?)?;
150 let literal_size = u16::from_bits_be(next_bits(16)?)?;
151 let literal = Literal::from_bits_be(literal_variant, next_bits(literal_size as usize)?)?;
152
153 Ok(Self::Literal(literal, OnceCell::with_value(bits_be.to_vec())))
155 }
156 else if variant == [false, true] {
158 let num_members = u8::from_bits_be(next_bits(8)?)?;
159 if num_members as usize > N::MAX_STRUCT_ENTRIES {
160 bail!("Struct exceeds maximum of entries.");
161 }
162 let mut members = IndexMap::with_capacity(num_members as usize);
163 for _ in 0..num_members {
164 let identifier_size = u8::from_bits_be(next_bits(8)?)?;
165 let identifier = Identifier::from_bits_be(next_bits(identifier_size as usize)?)?;
166 let member_size = u16::from_bits_be(next_bits(16)?)?;
167 let value = Plaintext::from_bits_be_internal(next_bits(member_size as usize)?, depth + 1)?;
168 if members.insert(identifier, value).is_some() {
169 bail!("Duplicate identifier in struct.");
170 }
171 }
172
173 Ok(Self::Struct(members, OnceCell::with_value(bits_be.to_vec())))
175 }
176 else if variant == [true, false] {
178 let num_elements = u32::from_bits_be(next_bits(32)?)?;
179 if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
180 bail!("Array exceeds maximum of elements.");
181 }
182
183 let mut elements = Vec::with_capacity(num_elements as usize);
184 for _ in 0..num_elements {
185 let element_size = u16::from_bits_be(next_bits(16)?)?;
186 let element = Plaintext::from_bits_be_internal(next_bits(element_size as usize)?, depth + 1)?;
187
188 elements.push(element);
189 }
190
191 Ok(Self::Array(elements, OnceCell::with_value(bits_be.to_vec())))
193 }
194 else {
196 bail!("Unknown plaintext variant - {variant:?}");
197 }
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use snarkvm_console_network::MainnetV0;
205
206 type CurrentNetwork = MainnetV0;
207
208 fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize {
210 match plaintext {
211 Plaintext::Literal(_, _) => 0,
212 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1,
213 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1,
214 }
215 }
216
217 #[test]
218 fn test_deeply_nested_plaintext_bits_le() {
219 fn create_nested_array(depth: usize, root: impl Display) -> Vec<bool> {
221 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
223 result.reverse();
225 for _ in 0..depth {
227 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
229 length.reverse();
230 result.extend(length);
231 let mut num_elements = 1u32.to_bits_le();
233 num_elements.reverse();
234 result.extend(num_elements);
235 result.extend([false, true]);
237 }
238 result.reverse();
240 result
241 }
242
243 fn create_nested_struct(depth: usize, root: impl Display) -> Vec<bool> {
245 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
247 result.reverse();
249 for _ in 0..depth {
251 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
253 length.reverse();
254 result.extend(length);
255 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le();
257 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le();
258 member_name.reverse();
259 result.extend(member_name);
260 member_name_length.reverse();
262 result.extend(member_name_length);
263 let mut num_members = 1u8.to_bits_le();
265 num_members.reverse();
266 result.extend(num_members);
267 result.extend([true, false]);
269 }
270 result.reverse();
272 result
273 }
274
275 fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<bool> {
277 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
279 result.reverse();
281 for i in 0..depth {
283 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
285 length.reverse();
286 result.extend(length);
287 if i % 2 == 0 {
289 let mut num_elements = 1u32.to_bits_le();
291 num_elements.reverse();
292 result.extend(num_elements);
293 result.extend([false, true]);
295 } else {
296 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le();
298 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le();
299 member_name.reverse();
300 result.extend(member_name);
301 member_name_length.reverse();
303 result.extend(member_name_length);
304 let mut num_members = 1u8.to_bits_le();
306 num_members.reverse();
307 result.extend(num_members);
308 result.extend([true, false]);
310 }
311 }
312 result.reverse();
314 result
315 }
316
317 fn run_test(expected_depth: usize, input: Vec<bool>, expected_error: bool) {
319 let result = Plaintext::<CurrentNetwork>::from_bits_le(&input);
321 match expected_error {
323 true => {
324 assert!(result.is_err());
325 return;
326 }
327 false => assert!(result.is_ok()),
328 };
329 let candidate = result.unwrap();
331 assert_eq!(input, candidate.to_bits_le());
333 assert_eq!(get_depth(&candidate), expected_depth);
335 }
336
337 let mut depths = (0usize..100).collect_vec();
340 depths.extend((100..890).step_by(10));
341
342 for i in depths.iter().copied() {
344 run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
345 run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
346 run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
347 run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
348 }
349
350 for i in depths.iter().copied() {
352 run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
353 run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
354 run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
355 run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
356 }
357
358 for i in depths.iter().copied() {
360 run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
361 run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
362 run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
363 run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
364 }
365 }
366
367 #[test]
368 fn test_deeply_nested_plaintext_bits_be() {
369 fn create_nested_array(depth: usize, root: impl Display) -> Vec<bool> {
371 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
373 result.reverse();
375 for _ in 0..depth {
377 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
379 length.reverse();
380 result.extend(length);
381 let mut num_elements = 1u32.to_bits_be();
383 num_elements.reverse();
384 result.extend(num_elements);
385 result.extend([false, true]);
387 }
388 result.reverse();
390 result
391 }
392
393 fn create_nested_struct(depth: usize, root: impl Display) -> Vec<bool> {
395 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
397 result.reverse();
399 for _ in 0..depth {
401 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
403 length.reverse();
404 result.extend(length);
405 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
407 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
408 member_name.reverse();
409 result.extend(member_name);
410 member_name_length.reverse();
412 result.extend(member_name_length);
413 let mut num_members = 1u8.to_bits_be();
415 num_members.reverse();
416 result.extend(num_members);
417 result.extend([true, false]);
419 }
420 result.reverse();
422 result
423 }
424
425 fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<bool> {
427 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
429 result.reverse();
431 for i in 0..depth {
433 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
435 length.reverse();
436 result.extend(length);
437 if i % 2 == 0 {
439 let mut num_elements = 1u32.to_bits_be();
441 num_elements.reverse();
442 result.extend(num_elements);
443 result.extend([false, true]);
445 } else {
446 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
448 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
449 member_name.reverse();
450 result.extend(member_name);
451 member_name_length.reverse();
453 result.extend(member_name_length);
454 let mut num_members = 1u8.to_bits_be();
456 num_members.reverse();
457 result.extend(num_members);
458 result.extend([true, false]);
460 }
461 }
462 result.reverse();
464 result
465 }
466
467 fn run_test(expected_depth: usize, input: Vec<bool>, expected_error: bool) {
469 let result = Plaintext::<CurrentNetwork>::from_bits_be(&input);
471 match expected_error {
473 true => {
474 assert!(result.is_err());
475 return;
476 }
477 false => assert!(result.is_ok()),
478 };
479 let candidate = result.unwrap();
481 assert_eq!(input, candidate.to_bits_be());
483 assert_eq!(get_depth(&candidate), expected_depth);
485 }
486
487 let mut depths = (0usize..100).collect_vec();
490 depths.extend((100..890).step_by(10));
491
492 for i in depths.iter().copied() {
494 run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
495 run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
496 run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
497 run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
498 }
499
500 for i in depths.iter().copied() {
502 run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
503 run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
504 run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
505 run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
506 }
507
508 for i in depths.iter().copied() {
510 run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
511 run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
512 run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
513 run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
514 }
515 }
516}