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