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