/ console / program / src / data / future / 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 Future<N> {
 19      /// Reads in a future from a buffer.
 20      fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
 21          // Read the future.
 22          Self::read_le_internal(&mut reader, 0)
 23      }
 24  }
 25  
 26  impl<N: Network> Future<N> {
 27      /// Reads in a future from a buffer, while tracking the depth of the data.
 28      fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self> {
 29          // Ensure that the depth is within the maximum limit.
 30          // Note: `N::MAX_DATA_DEPTH` is an upper bound on the number of nested futures.
 31          //  The true maximum is defined by `Transaction::<N>::MAX_TRANSITIONS`, however, that object is not accessible in this crate.
 32          //  In practice, `MAX_DATA_DEPTH` is 32, while `MAX_TRANSITIONS` is 31.
 33          //  TODO: @d0cd, should we use a more precise bound?
 34          if depth > N::MAX_DATA_DEPTH {
 35              return Err(error(format!(
 36                  "Failed to deserialize plaintext: Depth exceeds maximum limit: {}",
 37                  N::MAX_DATA_DEPTH
 38              )));
 39          }
 40          // Read the program ID.
 41          let program_id = ProgramID::read_le(&mut reader)?;
 42          // Read the function name.
 43          let function_name = Identifier::<N>::read_le(&mut reader)?;
 44          // Read the number of arguments to the future.
 45          let num_arguments = u8::read_le(&mut reader)? as usize;
 46          if num_arguments > N::MAX_INPUTS {
 47              return Err(error("Failed to read future: too many arguments"));
 48          };
 49          // Read the arguments.
 50          let mut arguments = Vec::with_capacity(num_arguments);
 51          for _ in 0..num_arguments {
 52              // Read the argument (in 2 steps to prevent infinite recursion).
 53              let num_bytes = u16::read_le(&mut reader)?;
 54              // Read the argument bytes.
 55              let mut bytes = Vec::new();
 56              (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
 57              // Recover the argument.
 58              let entry = Argument::read_le_internal(&mut bytes.as_slice(), depth)?;
 59              // Add the argument.
 60              arguments.push(entry);
 61          }
 62          // Return the future.
 63          Ok(Self::new(program_id, function_name, arguments))
 64      }
 65  }
 66  
 67  impl<N: Network> ToBytes for Future<N> {
 68      /// Writes a future to a buffer.
 69      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
 70          // Write the program ID.
 71          self.program_id.write_le(&mut writer)?;
 72          // Write the function name.
 73          self.function_name.write_le(&mut writer)?;
 74          // Write the number of arguments.
 75          if self.arguments.len() > N::MAX_INPUTS {
 76              return Err(error("Failed to write future: too many arguments"));
 77          };
 78          u8::try_from(self.arguments.len()).map_err(error)?.write_le(&mut writer)?;
 79          // Write each argument.
 80          for argument in &self.arguments {
 81              // Write the argument (performed in 2 steps to prevent infinite recursion).
 82              let bytes = argument.to_bytes_le().map_err(error)?;
 83              // Write the number of bytes.
 84              u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?;
 85              // Write the bytes.
 86              bytes.write_le(&mut writer)?;
 87          }
 88          Ok(())
 89      }
 90  }
 91  
 92  impl<N: Network> Argument<N> {
 93      fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self>
 94      where
 95          Self: Sized,
 96      {
 97          // Read the index.
 98          let index = u8::read_le(&mut reader)?;
 99          // Read the argument.
100          let argument = match index {
101              0 => Self::Plaintext(Plaintext::read_le(&mut reader)?),
102              1 => Self::Future(Future::read_le_internal(&mut reader, depth + 1)?),
103              2.. => return Err(error(format!("Failed to decode future argument {index}"))),
104          };
105          Ok(argument)
106      }
107  }
108  
109  impl<N: Network> ToBytes for Argument<N> {
110      fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
111          match self {
112              Self::Plaintext(plaintext) => {
113                  0u8.write_le(&mut writer)?;
114                  plaintext.write_le(&mut writer)
115              }
116              Self::Future(future) => {
117                  1u8.write_le(&mut writer)?;
118                  future.write_le(&mut writer)
119              }
120          }
121      }
122  }
123  
124  #[cfg(test)]
125  mod tests {
126      use super::*;
127      use alphavm_console_network::MainnetV0;
128  
129      type CurrentNetwork = MainnetV0;
130  
131      #[test]
132      fn test_bytes() -> Result<()> {
133          // Check the future manually.
134          let expected = Future::<CurrentNetwork>::from_str(
135              "{ program_id: credits.alpha, function_name: transfer, arguments: [] }",
136          )?;
137  
138          // Check the byte representation.
139          let expected_bytes = expected.to_bytes_le()?;
140          assert_eq!(expected, Future::read_le(&expected_bytes[..])?);
141  
142          Ok(())
143      }
144  
145      // A helper function to get the depth of a future.
146      fn get_depth<N: Network>(future: &Future<N>) -> usize {
147          // Count the number of nested futures.
148          future
149              .arguments
150              .iter()
151              .map(|arg| match arg {
152                  Argument::Plaintext(_) => 0,
153                  Argument::Future(future) => 1 + get_depth(future),
154              })
155              .sum()
156      }
157  
158      #[test]
159      fn test_deeply_nested_future() {
160          // Creates a nested `Future`.
161          // This method is iterative to avoid stack overflows.
162          fn create_nested_future(depth: usize) -> Vec<u8> {
163              // Start from the innermost value.
164              let mut result = Future::<CurrentNetwork>::from_str(
165                  r"{
166                  program_id: foo.alpha,
167                  function_name: bar,
168                  arguments: []
169              }",
170              )
171              .unwrap()
172              .to_bytes_le()
173              .unwrap();
174              // Reverse the bytes.
175              result.reverse();
176              // Build up the structure in reverse.
177              for _ in 0..depth {
178                  // Write the variant of the argument in reverse.
179                  let mut variant = 1u8.to_bytes_le().unwrap();
180                  variant.reverse();
181                  result.extend(variant);
182                  // Write the size of the object in bytes in reverse.
183                  let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap();
184                  length.reverse();
185                  result.extend(length);
186                  // Write the number of arguments in reverse.
187                  let mut num_elements = 1u8.to_bytes_le().unwrap();
188                  num_elements.reverse();
189                  result.extend(num_elements);
190                  // Write the function name in reverse.
191                  let mut function_name = Identifier::<CurrentNetwork>::from_str("bar").unwrap().to_bytes_le().unwrap();
192                  function_name.reverse();
193                  result.extend(function_name);
194                  // Write the program ID in reverse.
195                  let mut program_id = ProgramID::<CurrentNetwork>::from_str("foo.alpha").unwrap().to_bytes_le().unwrap();
196                  program_id.reverse();
197                  result.extend(program_id);
198              }
199              // Reverse the result to get the correct order.
200              result.reverse();
201              result
202          }
203  
204          // A helper function to run the test.
205          fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) {
206              // Parse the input string.
207              let result = Future::<CurrentNetwork>::read_le(&*input);
208              // // Check if the result is an error.
209              match expected_error {
210                  true => {
211                      assert!(result.is_err());
212                      return;
213                  }
214                  false => assert!(result.is_ok()),
215              };
216              // Unwrap the result.
217              let candidate = result.unwrap();
218              // Check if the candidate is equal to the input, with whitespace removed.
219              assert_eq!(input, candidate.to_bytes_le().unwrap());
220              // Check if the candidate is equal to the expected depth.
221              assert_eq!(get_depth(&candidate), expected_depth);
222          }
223  
224          // Initialize a sequence of depths to check.
225          // Note: It is not possible to create a `Future` of depth 3600 in this test as it's size would exceed `u16::MAX`.
226          // (The limit is lower than before due to "alpha" being 5 chars vs "aleo" being 4 chars.)
227          let mut depths = (0usize..100).collect_vec();
228          depths.extend((100..3500).step_by(100));
229  
230          // Test deeply nested arrays with different literal types.
231          for i in depths.iter().copied() {
232              run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
233              run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
234              run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
235              run_test(i, create_nested_future(i), i > CurrentNetwork::MAX_DATA_DEPTH);
236          }
237      }
238  }