/ console / program / src / data / plaintext / bytes.rs
bytes.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> FromBytes for Plaintext<N> {
 22      /// Reads the plaintext from a buffer.
 23      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
 24          Self::read_le_internal(&mut reader, 0)
 25      }
 26  }
 27  
 28  impl<N: Network> Plaintext<N> {
 29      /// Reads the plaintext from a buffer, while tracking the depth of the data.
 30      fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self> {
 31          // Ensure that the depth is within the maximum limit.
 32          if depth > N::MAX_DATA_DEPTH {
 33              return Err(error(format!(
 34                  "Failed to deserialize plaintext: Depth exceeds maximum limit: {}",
 35                  N::MAX_DATA_DEPTH
 36              )));
 37          }
 38          // Read the index.
 39          let index = u8::read_le(&mut reader)?;
 40          // Read the plaintext.
 41          let plaintext = match index {
 42              0 => Self::Literal(Literal::read_le(&mut reader)?, Default::default()),
 43              1 => {
 44                  // Read the number of members in the struct.
 45                  let num_members = u8::read_le(&mut reader)?;
 46                  // Read the members.
 47                  let mut members = IndexMap::with_capacity(num_members as usize);
 48                  for _ in 0..num_members {
 49                      // Read the identifier.
 50                      let identifier = Identifier::<N>::read_le(&mut reader)?;
 51                      // Read the plaintext value (in 2 steps to prevent infinite recursion).
 52                      let num_bytes = u16::read_le(&mut reader)?;
 53                      // Read the plaintext bytes.
 54                      let mut bytes = Vec::new();
 55                      (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
 56                      // Recover the plaintext value.
 57                      let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?;
 58                      // Add the member.
 59                      members.insert(identifier, plaintext);
 60                  }
 61                  // Return the struct.
 62                  Self::Struct(members, Default::default())
 63              }
 64              2 => {
 65                  // Read the length of the array.
 66                  let num_elements = u32::read_le(&mut reader)?;
 67                  if num_elements as usize > N::MAX_ARRAY_ELEMENTS {
 68                      return Err(error("Failed to deserialize plaintext: Array exceeds maximum length"));
 69                  }
 70                  // Read the elements.
 71                  let mut elements = Vec::with_capacity(num_elements as usize);
 72                  for _ in 0..num_elements {
 73                      // Read the plaintext value (in 2 steps to prevent infinite recursion).
 74                      let num_bytes = u16::read_le(&mut reader)?;
 75                      // Read the plaintext bytes.
 76                      let mut bytes = Vec::new();
 77                      (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
 78                      // Recover the plaintext value.
 79                      let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?;
 80                      // Add the element.
 81                      elements.push(plaintext);
 82                  }
 83                  // Return the array.
 84                  Self::Array(elements, Default::default())
 85              }
 86              3.. => return Err(error(format!("Failed to decode plaintext variant {index}"))),
 87          };
 88          Ok(plaintext)
 89      }
 90  }
 91  
 92  impl<N: Network> ToBytes for Plaintext<N> {
 93      /// Writes the plaintext to a buffer.
 94      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
 95          match self {
 96              Self::Literal(literal, ..) => {
 97                  0u8.write_le(&mut writer)?;
 98                  literal.write_le(&mut writer)
 99              }
100              Self::Struct(struct_, ..) => {
101                  1u8.write_le(&mut writer)?;
102  
103                  // Write the number of members in the struct.
104                  u8::try_from(struct_.len()).map_err(error)?.write_le(&mut writer)?;
105  
106                  // Write each member.
107                  for (member_name, member_value) in struct_ {
108                      // Write the member name.
109                      member_name.write_le(&mut writer)?;
110  
111                      // Write the member value (performed in 2 steps to prevent infinite recursion).
112                      let bytes = member_value.to_bytes_le().map_err(|e| error(e.to_string()))?;
113                      // Write the number of bytes.
114                      u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
115                      // Write the bytes.
116                      bytes.write_le(&mut writer)?;
117                  }
118                  Ok(())
119              }
120              Self::Array(array, ..) => {
121                  2u8.write_le(&mut writer)?;
122  
123                  // Write the length of the array.
124                  u32::try_from(array.len()).map_err(error)?.write_le(&mut writer)?;
125  
126                  // Write each element.
127                  for element in array {
128                      // Write the element (performed in 2 steps to prevent infinite recursion).
129                      let bytes = element.to_bytes_le().map_err(error)?;
130                      // Write the number of bytes.
131                      u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
132                      // Write the bytes.
133                      bytes.write_le(&mut writer)?;
134                  }
135                  Ok(())
136              }
137          }
138      }
139  }
140  
141  #[cfg(test)]
142  mod tests {
143      use super::*;
144      use alphavm_console_network::MainnetV0;
145  
146      type CurrentNetwork = MainnetV0;
147  
148      const ITERATIONS: u32 = 1000;
149  
150      fn check_bytes(expected: Plaintext<CurrentNetwork>) -> Result<()> {
151          // Check the byte representation.
152          let expected_bytes = expected.to_bytes_le()?;
153          assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
154          Ok(())
155      }
156  
157      #[test]
158      fn test_bytes() -> Result<()> {
159          let rng = &mut TestRng::default();
160  
161          for _ in 0..ITERATIONS {
162              let private_key = alphavm_console_account::PrivateKey::<CurrentNetwork>::new(rng)?;
163  
164              // Address
165              check_bytes(Plaintext::Literal(
166                  Literal::<CurrentNetwork>::Address(Address::try_from(private_key)?),
167                  Default::default(),
168              ))?;
169              // Boolean
170              check_bytes(Plaintext::Literal(
171                  Literal::<CurrentNetwork>::Boolean(Boolean::new(Uniform::rand(rng))),
172                  Default::default(),
173              ))?;
174              // Field
175              check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Field(Uniform::rand(rng)), Default::default()))?;
176              // Group
177              check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Group(Uniform::rand(rng)), Default::default()))?;
178              // I8
179              check_bytes(Plaintext::Literal(
180                  Literal::<CurrentNetwork>::I8(I8::new(Uniform::rand(rng))),
181                  Default::default(),
182              ))?;
183              // I16
184              check_bytes(Plaintext::Literal(
185                  Literal::<CurrentNetwork>::I16(I16::new(Uniform::rand(rng))),
186                  Default::default(),
187              ))?;
188              // I32
189              check_bytes(Plaintext::Literal(
190                  Literal::<CurrentNetwork>::I32(I32::new(Uniform::rand(rng))),
191                  Default::default(),
192              ))?;
193              // I64
194              check_bytes(Plaintext::Literal(
195                  Literal::<CurrentNetwork>::I64(I64::new(Uniform::rand(rng))),
196                  Default::default(),
197              ))?;
198              // I128
199              check_bytes(Plaintext::Literal(
200                  Literal::<CurrentNetwork>::I128(I128::new(Uniform::rand(rng))),
201                  Default::default(),
202              ))?;
203              // U8
204              check_bytes(Plaintext::Literal(
205                  Literal::<CurrentNetwork>::U8(U8::new(Uniform::rand(rng))),
206                  Default::default(),
207              ))?;
208              // U16
209              check_bytes(Plaintext::Literal(
210                  Literal::<CurrentNetwork>::U16(U16::new(Uniform::rand(rng))),
211                  Default::default(),
212              ))?;
213              // U32
214              check_bytes(Plaintext::Literal(
215                  Literal::<CurrentNetwork>::U32(U32::new(Uniform::rand(rng))),
216                  Default::default(),
217              ))?;
218              // U64
219              check_bytes(Plaintext::Literal(
220                  Literal::<CurrentNetwork>::U64(U64::new(Uniform::rand(rng))),
221                  Default::default(),
222              ))?;
223              // U128
224              check_bytes(Plaintext::Literal(
225                  Literal::<CurrentNetwork>::U128(U128::new(Uniform::rand(rng))),
226                  Default::default(),
227              ))?;
228              // Scalar
229              check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Scalar(Uniform::rand(rng)), Default::default()))?;
230              // String
231              check_bytes(Plaintext::Literal(
232                  Literal::<CurrentNetwork>::String(StringType::rand(rng)),
233                  Default::default(),
234              ))?;
235          }
236  
237          // Check the struct manually.
238          let expected = Plaintext::<CurrentNetwork>::from_str(
239              "{ owner: ax150w2lvhdzychwvzu54ys5zas7tm5s0ycdyw563pms83g9u0vucgqe5fs5w, token_amount: 100u64 }",
240          )?;
241  
242          // Check the byte representation.
243          let expected_bytes = expected.to_bytes_le()?;
244          assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
245  
246          // Check the array manually.
247          let expected = Plaintext::<CurrentNetwork>::from_str("[ 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8 ]")?;
248  
249          // Check the byte representation.
250          let expected_bytes = expected.to_bytes_le()?;
251          assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?);
252  
253          Ok(())
254      }
255  
256      // A helper function to get the depth of the plaintext.
257      fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize {
258          match plaintext {
259              Plaintext::Literal(_, _) => 0,
260              Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1,
261              Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1,
262          }
263      }
264  
265      #[test]
266      fn test_deeply_nested_plaintext() {
267          // Creates a nested array-like `Plaintext` structure by wrapping a root value `depth` times.
268          fn create_nested_array(depth: usize, root: impl Display) -> Vec<u8> {
269              // Start from the innermost value.
270              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
271              // Reverse the bytes.
272              result.reverse();
273              // Build up the structure in reverse.
274              for _ in 0..depth {
275                  // Write the size of the object in bytes in reverse.
276                  let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
277                  length.reverse();
278                  result.extend(length);
279                  // Write the number of elements in the array in reverse.
280                  let mut num_elements = 1u32.to_bytes_le().unwrap();
281                  num_elements.reverse();
282                  result.extend(num_elements);
283                  // Write the plaintext variant in reverse.
284                  let mut variant = 2u8.to_bytes_le().unwrap();
285                  variant.reverse();
286                  result.extend(variant);
287              }
288              // Reverse the result to get the correct order.
289              result.reverse();
290              result
291          }
292  
293          // Creates a nested struct-like `Plaintext` structure by wrapping a root value `depth` times.
294          fn create_nested_struct(depth: usize, root: impl Display) -> Vec<u8> {
295              // Start from the innermost value.
296              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
297              // Reverse the bytes.
298              result.reverse();
299              // Build up the structure in reverse.
300              for _ in 0..depth {
301                  // Write the size of the object in bytes in reverse.
302                  let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
303                  length.reverse();
304                  result.extend(length);
305                  // Write the member name in reverse.
306                  let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap();
307                  member_name.reverse();
308                  result.extend(member_name);
309                  // Write the number of members in the struct in reverse.
310                  let mut num_members = 1u8.to_bytes_le().unwrap();
311                  num_members.reverse();
312                  result.extend(num_members);
313                  // Write the plaintext variant in reverse.
314                  let mut variant = 1u8.to_bytes_le().unwrap();
315                  variant.reverse();
316                  result.extend(variant);
317              }
318              // Reverse the result to get the correct order.
319              result.reverse();
320              result
321          }
322  
323          // Creates a nested `Plaintext` structure with alternating array and struct wrappers.
324          fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<u8> {
325              // Start from the innermost value.
326              let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap();
327              // Reverse the bytes.
328              result.reverse();
329              // Build up the structure in reverse.
330              for i in 0..depth {
331                  // Write the size of the object in bytes in reverse.
332                  let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
333                  length.reverse();
334                  result.extend(length);
335                  // Determine the type of the wrapper (array or struct) and handle accordingly.
336                  if i % 2 == 0 {
337                      // Write the number of elements in the array in reverse.
338                      let mut num_elements = 1u32.to_bytes_le().unwrap();
339                      num_elements.reverse();
340                      result.extend(num_elements);
341                      // Write the plaintext variant for array in reverse.
342                      let mut variant = 2u8.to_bytes_le().unwrap();
343                      variant.reverse();
344                      result.extend(variant);
345                  } else {
346                      // Write the member name in reverse.
347                      let mut member_name =
348                          Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap();
349                      member_name.reverse();
350                      result.extend(member_name);
351                      // Write the number of members in the struct in reverse.
352                      let mut num_members = 1u8.to_bytes_le().unwrap();
353                      num_members.reverse();
354                      result.extend(num_members);
355                      // Write the plaintext variant for struct in reverse.
356                      let mut variant = 1u8.to_bytes_le().unwrap();
357                      variant.reverse();
358                      result.extend(variant);
359                  }
360              }
361              // Reverse the result to get the correct order.
362              result.reverse();
363              result
364          }
365  
366          // A helper function to run the test.
367          fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) {
368              // Parse the input string.
369              let result = Plaintext::<CurrentNetwork>::read_le(&*input);
370              // Check if the result is an error.
371              match expected_error {
372                  true => {
373                      assert!(result.is_err());
374                      return;
375                  }
376                  false => assert!(result.is_ok()),
377              };
378              // Unwrap the result.
379              let candidate = result.unwrap();
380              // Check if the candidate is equal to the input.
381              assert_eq!(input, candidate.to_bytes_le().unwrap());
382              // Check if the candidate is equal to the expected depth.
383              assert_eq!(get_depth(&candidate), expected_depth);
384          }
385  
386          // Initialize a sequence of depths to check.
387          // Note that 6500 is approximate maximum depth that can be constructed in this test.
388          let mut depths = (0usize..100).collect_vec();
389          depths.extend((100..6500).step_by(100));
390  
391          // Test deeply nested arrays with different literal types.
392          for i in depths.iter().copied() {
393              run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
394              run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
395              run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
396              run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
397          }
398  
399          // Test deeply nested structs with different literal types.
400          for i in depths.iter().copied() {
401              run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
402              run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
403              run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
404              run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
405          }
406  
407          // Test alternating nested arrays and structs.
408          for i in depths.iter().copied() {
409              run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH);
410              run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH);
411              run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH);
412              run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH);
413          }
414      }
415  }