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 }