/ console / program / src / data / plaintext / from_bits.rs
from_bits.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphavm library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  use super::*;
 20  
 21  impl<N: Network> FromBits for Plaintext<N> {
 22      /// Initializes a new plaintext from a list of little-endian bits *without* trailing zeros.
 23      fn from_bits_le(bits_le: &[bool]) -> Result<Self> {
 24          Self::from_bits_le_internal(bits_le, 0)
 25      }
 26  
 27      /// Initializes a new plaintext from a list of big-endian bits *without* trailing zeros.
 28      fn from_bits_be(bits_be: &[bool]) -> Result<Self> {
 29          Self::from_bits_be_internal(bits_be, 0)
 30      }
 31  }
 32  
 33  impl<N: Network> Plaintext<N> {
 34      /// Initializes a new plaintext from a list of little-endian bits *without* trailing zeros, while the depth of the data.
 35      fn from_bits_le_internal(bits_le: &[bool], depth: usize) -> Result<Self> {
 36          // Ensure that the depth is within the maximum limit.
 37          if depth > N::MAX_DATA_DEPTH {
 38              bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
 39          }
 40  
 41          let bits = bits_le;
 42  
 43          // The starting index used to create subsequent subslices of the `bits` slice.
 44          let mut index = 0;
 45  
 46          // Helper function to get the next n bits as a slice.
 47          let mut next_bits = |n: usize| -> Result<&[bool]> {
 48              // Safely procure a subslice with the length `n` starting at `index`.
 49              let subslice = bits.get(index..index + n);
 50              // Check if the range is within bounds.
 51              if let Some(next_bits) = subslice {
 52                  // Move the starting index.
 53                  index += n;
 54                  // Return the subslice.
 55                  Ok(next_bits)
 56              } else {
 57                  bail!("Insufficient bits");
 58              }
 59          };
 60  
 61          let variant = next_bits(2)?;
 62          let variant = [variant[0], variant[1]];
 63  
 64          // Literal
 65          if variant == PlaintextType::<N>::LITERAL_PREFIX_BITS {
 66              let literal_variant = u8::from_bits_le(next_bits(8)?)?;
 67              let literal_size = u16::from_bits_le(next_bits(16)?)?;
 68              let literal = Literal::from_bits_le(literal_variant, next_bits(literal_size as usize)?)?;
 69  
 70              // Cache the plaintext bits, and return the literal.
 71              Ok(Self::Literal(literal, bits_le.to_vec().into()))
 72          }
 73          // Struct
 74          else if variant == PlaintextType::<N>::STRUCT_PREFIX_BITS {
 75              let num_members = u8::from_bits_le(next_bits(8)?)?;
 76              if num_members as usize > N::MAX_STRUCT_ENTRIES {
 77                  bail!("Struct exceeds maximum of entries.");
 78              }
 79  
 80              let mut members = IndexMap::with_capacity(num_members as usize);
 81              for _ in 0..num_members {
 82                  let identifier_size = u8::from_bits_le(next_bits(8)?)?;
 83                  let identifier = Identifier::from_bits_le(next_bits(identifier_size as usize)?)?;
 84  
 85                  let member_size = u16::from_bits_le(next_bits(16)?)?;
 86                  let value = Plaintext::from_bits_le_internal(next_bits(member_size as usize)?, depth + 1)?;
 87  
 88                  if members.insert(identifier, value).is_some() {
 89                      bail!("Duplicate identifier in struct.");
 90                  }
 91              }
 92  
 93              // Cache the plaintext bits, and return the struct.
 94              Ok(Self::Struct(members, bits_le.to_vec().into()))
 95          }
 96          // Array
 97          else if variant == PlaintextType::<N>::ARRAY_PREFIX_BITS {
 98              let num_elements = u32::from_bits_le(next_bits(32)?)?;
 99              if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
100                  bail!("Array exceeds maximum of elements.");
101              }
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)?)?;
106                  let element = Plaintext::from_bits_le_internal(next_bits(element_size as usize)?, depth + 1)?;
107  
108                  elements.push(element);
109              }
110  
111              // Cache the plaintext bits, and return the array.
112              Ok(Self::Array(elements, bits_le.to_vec().into()))
113          }
114          // Unknown variant.
115          else {
116              bail!("Unknown plaintext variant - {variant:?}");
117          }
118      }
119  
120      /// Initializes a new plaintext from a list of big-endian bits *without* trailing zeros, while tracking the depth of the data.
121      fn from_bits_be_internal(bits_be: &[bool], depth: usize) -> Result<Self> {
122          // Ensure that the depth is within the maximum limit.
123          if depth > N::MAX_DATA_DEPTH {
124              bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH)
125          }
126  
127          let bits = bits_be;
128  
129          // The starting index used to create subsequent subslices of the `bits` slice.
130          let mut index = 0;
131  
132          // Helper function to get the next n bits as a slice.
133          let mut next_bits = |n: usize| -> Result<&[bool]> {
134              // Safely procure a subslice with the length `n` starting at `index`.
135              let subslice = bits.get(index..index + n);
136              // Check if the range is within bounds.
137              if let Some(next_bits) = subslice {
138                  // Move the starting index.
139                  index += n;
140                  // Return the subslice.
141                  Ok(next_bits)
142              } else {
143                  bail!("Insufficient bits");
144              }
145          };
146  
147          let variant = next_bits(2)?;
148          let variant = [variant[0], variant[1]];
149  
150          // Literal
151          if variant == PlaintextType::<N>::LITERAL_PREFIX_BITS {
152              let literal_variant = u8::from_bits_be(next_bits(8)?)?;
153              let literal_size = u16::from_bits_be(next_bits(16)?)?;
154              let literal = Literal::from_bits_be(literal_variant, next_bits(literal_size as usize)?)?;
155  
156              // Cache the plaintext bits, and return the literal.
157              Ok(Self::Literal(literal, bits_be.to_vec().into()))
158          }
159          // Struct
160          else if variant == PlaintextType::<N>::STRUCT_PREFIX_BITS {
161              let num_members = u8::from_bits_be(next_bits(8)?)?;
162              if num_members as usize > N::MAX_STRUCT_ENTRIES {
163                  bail!("Struct exceeds maximum of entries.");
164              }
165              let mut members = IndexMap::with_capacity(num_members as usize);
166              for _ in 0..num_members {
167                  let identifier_size = u8::from_bits_be(next_bits(8)?)?;
168                  let identifier = Identifier::from_bits_be(next_bits(identifier_size as usize)?)?;
169                  let member_size = u16::from_bits_be(next_bits(16)?)?;
170                  let value = Plaintext::from_bits_be_internal(next_bits(member_size as usize)?, depth + 1)?;
171                  if members.insert(identifier, value).is_some() {
172                      bail!("Duplicate identifier in struct.");
173                  }
174              }
175  
176              // Cache the plaintext bits, and return the struct.
177              Ok(Self::Struct(members, bits_be.to_vec().into()))
178          }
179          // Array
180          else if variant == PlaintextType::<N>::ARRAY_PREFIX_BITS {
181              let num_elements = u32::from_bits_be(next_bits(32)?)?;
182              if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
183                  bail!("Array exceeds maximum of elements.");
184              }
185  
186              let mut elements = Vec::with_capacity(num_elements as usize);
187              for _ in 0..num_elements {
188                  let element_size = u16::from_bits_be(next_bits(16)?)?;
189                  let element = Plaintext::from_bits_be_internal(next_bits(element_size as usize)?, depth + 1)?;
190  
191                  elements.push(element);
192              }
193  
194              // Cache the plaintext bits, and return the array.
195              Ok(Self::Array(elements, bits_be.to_vec().into()))
196          }
197          // Unknown variant.
198          else {
199              bail!("Unknown plaintext variant - {variant:?}");
200          }
201      }
202  }
203  
204  #[cfg(test)]
205  mod tests {
206      use super::*;
207      use alphavm_console_network::MainnetV0;
208  
209      type CurrentNetwork = MainnetV0;
210  
211      // A helper function to get the depth of the plaintext.
212      fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize {
213          match plaintext {
214              Plaintext::Literal(_, _) => 0,
215              Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1,
216              Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1,
217          }
218      }
219  
220      #[test]
221      fn test_deeply_nested_plaintext_bits_le() {
222          // Creates a nested array-like `Plaintext` structure by wrapping a root value `depth` times.
223          fn create_nested_array(depth: usize, root: impl Display) -> Vec<bool> {
224              // Start from the innermost value.
225              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
226              // Reverse the bytes.
227              result.reverse();
228              // Build up the structure in reverse.
229              for _ in 0..depth {
230                  // Write the size of the object in bits in reverse.
231                  let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
232                  length.reverse();
233                  result.extend(length);
234                  // Write the number of elements in the array in reverse.
235                  let mut num_elements = 1u32.to_bits_le();
236                  num_elements.reverse();
237                  result.extend(num_elements);
238                  // Write the plaintext variant in reverse.
239                  result.extend([false, true]);
240              }
241              // Reverse the result to get the correct order.
242              result.reverse();
243              result
244          }
245  
246          // Creates a nested struct-like `Plaintext` structure by wrapping a root value `depth` times.
247          fn create_nested_struct(depth: usize, root: impl Display) -> Vec<bool> {
248              // Start from the innermost value.
249              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
250              // Reverse the bytes.
251              result.reverse();
252              // Build up the structure in reverse.
253              for _ in 0..depth {
254                  // Write the size of the object in bits in reverse.
255                  let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
256                  length.reverse();
257                  result.extend(length);
258                  // Write the member name in reverse.
259                  let mut member_name = 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                  // Write the length of the member name in reverse.
264                  member_name_length.reverse();
265                  result.extend(member_name_length);
266                  // Write the number of members in the struct in reverse.
267                  let mut num_members = 1u8.to_bits_le();
268                  num_members.reverse();
269                  result.extend(num_members);
270                  // Write the plaintext variant in reverse.
271                  result.extend([true, false]);
272              }
273              // Reverse the result to get the correct order.
274              result.reverse();
275              result
276          }
277  
278          // Creates a nested `Plaintext` structure with alternating array and struct wrappers.
279          fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<bool> {
280              // Start from the innermost value.
281              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le();
282              // Reverse the bytes.
283              result.reverse();
284              // Build up the structure in reverse.
285              for i in 0..depth {
286                  // Write the size of the object in bits in reverse.
287                  let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le();
288                  length.reverse();
289                  result.extend(length);
290                  // Determine the type of the wrapper (array or struct) and handle accordingly.
291                  if i % 2 == 0 {
292                      // Write the number of elements in the array in reverse.
293                      let mut num_elements = 1u32.to_bits_le();
294                      num_elements.reverse();
295                      result.extend(num_elements);
296                      // Write the plaintext variant for array in reverse.
297                      result.extend([false, true]);
298                  } else {
299                      // Write the member name in reverse.
300                      let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le();
301                      let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le();
302                      member_name.reverse();
303                      result.extend(member_name);
304                      // Write the member name length in reverse.
305                      member_name_length.reverse();
306                      result.extend(member_name_length);
307                      // Write the number of members in the struct in reverse.
308                      let mut num_members = 1u8.to_bits_le();
309                      num_members.reverse();
310                      result.extend(num_members);
311                      // Write the plaintext variant for struct in reverse.
312                      result.extend([true, false]);
313                  }
314              }
315              // Reverse the result to get the correct order.
316              result.reverse();
317              result
318          }
319  
320          // A helper function to run the test.
321          fn run_test(expected_depth: usize, input: Vec<bool>, expected_error: bool) {
322              // Parse the input string.
323              let result = Plaintext::<CurrentNetwork>::from_bits_le(&input);
324              // Check if the result is an error.
325              match expected_error {
326                  true => {
327                      assert!(result.is_err());
328                      return;
329                  }
330                  false => assert!(result.is_ok()),
331              };
332              // Unwrap the result.
333              let candidate = result.unwrap();
334              // Check if the candidate is equal to the input.
335              assert_eq!(input, candidate.to_bits_le());
336              // Check if the depth of the candidate is equal to the expected depth.
337              assert_eq!(get_depth(&candidate), expected_depth);
338          }
339  
340          // Initialize a sequence of depths to check.
341          // Note that 890 is approximate maximum depth that can be constructed in this test.
342          let mut depths = (0usize..100).collect_vec();
343          depths.extend((100..890).step_by(10));
344  
345          // Test deeply nested arrays with different literal types.
346          for i in depths.iter().copied() {
347              run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
348              run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
349              run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
350              run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
351          }
352  
353          // Test deeply nested structs with different literal types.
354          for i in depths.iter().copied() {
355              run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
356              run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
357              run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
358              run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
359          }
360  
361          // Test alternating nested arrays and structs.
362          for i in depths.iter().copied() {
363              run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
364              run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
365              run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
366              run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
367          }
368      }
369  
370      #[test]
371      fn test_deeply_nested_plaintext_bits_be() {
372          // Creates a nested array-like `Plaintext` structure by wrapping a root value `depth` times.
373          fn create_nested_array(depth: usize, root: impl Display) -> Vec<bool> {
374              // Start from the innermost value.
375              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
376              // Reverse the bits.
377              result.reverse();
378              // Build up the structure in reverse.
379              for _ in 0..depth {
380                  // Write the size of the object in bits in reverse.
381                  let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
382                  length.reverse();
383                  result.extend(length);
384                  // Write the number of elements in the array in reverse.
385                  let mut num_elements = 1u32.to_bits_be();
386                  num_elements.reverse();
387                  result.extend(num_elements);
388                  // Write the plaintext variant in reverse.
389                  result.extend([false, true]);
390              }
391              // Reverse the result to get the correct order.
392              result.reverse();
393              result
394          }
395  
396          // Creates a nested struct-like `Plaintext` structure by wrapping a root value `depth` times.
397          fn create_nested_struct(depth: usize, root: impl Display) -> Vec<bool> {
398              // Start from the innermost value.
399              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
400              // Reverse the bytes.
401              result.reverse();
402              // Build up the structure in reverse.
403              for _ in 0..depth {
404                  // Write the size of the object in bits in reverse.
405                  let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
406                  length.reverse();
407                  result.extend(length);
408                  // Write the member name in reverse.
409                  let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
410                  let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
411                  member_name.reverse();
412                  result.extend(member_name);
413                  // Write the length of the member name in reverse.
414                  member_name_length.reverse();
415                  result.extend(member_name_length);
416                  // Write the number of members in the struct in reverse.
417                  let mut num_members = 1u8.to_bits_be();
418                  num_members.reverse();
419                  result.extend(num_members);
420                  // Write the plaintext variant in reverse.
421                  result.extend([true, false]);
422              }
423              // Reverse the result to get the correct order.
424              result.reverse();
425              result
426          }
427  
428          // Creates a nested `Plaintext` structure with alternating array and struct wrappers.
429          fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<bool> {
430              // Start from the innermost value.
431              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be();
432              // Reverse the bytes.
433              result.reverse();
434              // Build up the structure in reverse.
435              for i in 0..depth {
436                  // Write the size of the object in bits in reverse.
437                  let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be();
438                  length.reverse();
439                  result.extend(length);
440                  // Determine the type of the wrapper (array or struct) and handle accordingly.
441                  if i % 2 == 0 {
442                      // Write the number of elements in the array in reverse.
443                      let mut num_elements = 1u32.to_bits_be();
444                      num_elements.reverse();
445                      result.extend(num_elements);
446                      // Write the plaintext variant for array in reverse.
447                      result.extend([false, true]);
448                  } else {
449                      // Write the member name in reverse.
450                      let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be();
451                      let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be();
452                      member_name.reverse();
453                      result.extend(member_name);
454                      // Write the member name length in reverse.
455                      member_name_length.reverse();
456                      result.extend(member_name_length);
457                      // Write the number of members in the struct in reverse.
458                      let mut num_members = 1u8.to_bits_be();
459                      num_members.reverse();
460                      result.extend(num_members);
461                      // Write the plaintext variant for struct in reverse.
462                      result.extend([true, false]);
463                  }
464              }
465              // Reverse the result to get the correct order.
466              result.reverse();
467              result
468          }
469  
470          // A helper function to run the test.
471          fn run_test(expected_depth: usize, input: Vec<bool>, expected_error: bool) {
472              // Parse the input string.
473              let result = Plaintext::<CurrentNetwork>::from_bits_be(&input);
474              // Check if the result is an error.
475              match expected_error {
476                  true => {
477                      assert!(result.is_err());
478                      return;
479                  }
480                  false => assert!(result.is_ok()),
481              };
482              // Unwrap the result.
483              let candidate = result.unwrap();
484              // Check if the candidate is equal to the input.
485              assert_eq!(input, candidate.to_bits_be());
486              // Check if the depth of the candidate is equal to the expected depth.
487              assert_eq!(get_depth(&candidate), expected_depth);
488          }
489  
490          // Initialize a sequence of depths to check.
491          // Note that 890 is approximate maximum depth that can be constructed in this test.
492          let mut depths = (0usize..100).collect_vec();
493          depths.extend((100..890).step_by(10));
494  
495          // Test deeply nested arrays with different literal types.
496          for i in depths.iter().copied() {
497              run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
498              run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
499              run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
500              run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
501          }
502  
503          // Test deeply nested structs with different literal types.
504          for i in depths.iter().copied() {
505              run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
506              run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
507              run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
508              run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
509          }
510  
511          // Test alternating nested arrays and structs.
512          for i in depths.iter().copied() {
513              run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
514              run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
515              run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
516              run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
517          }
518      }
519  }