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 }