parse.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> Parser for Future<N> { 22 /// Parses a string into a future value. 23 #[inline] 24 fn parse(string: &str) -> ParserResult<'_, Self> { 25 // Parse the future from the string. 26 Self::parse_internal(string, 0) 27 } 28 } 29 30 impl<N: Network> Future<N> { 31 /// Parses an array of future arguments: `[arg_0, ..., arg_1]`, while tracking the depth of the data. 32 fn parse_arguments(string: &str, depth: usize) -> ParserResult<'_, Vec<Argument<N>>> { 33 // Parse the whitespace and comments from the string. 34 let (string, _) = Sanitizer::parse(string)?; 35 // Parse the "[" from the string. 36 let (string, _) = tag("[")(string)?; 37 // Parse the whitespace from the string. 38 let (string, _) = Sanitizer::parse(string)?; 39 // Parse the members. 40 let (string, arguments) = separated_list0( 41 pair(pair(Sanitizer::parse_whitespaces, tag(",")), Sanitizer::parse), 42 alt(( 43 map(|input| Self::parse_internal(input, depth + 1), Argument::Future), 44 map(Plaintext::parse, Argument::Plaintext), 45 )), 46 )(string)?; 47 // Parse the whitespace and comments from the string. 48 let (string, _) = Sanitizer::parse(string)?; 49 // Parse the ']' from the string. 50 let (string, _) = tag("]")(string)?; 51 // Output the plaintext. 52 Ok((string, arguments)) 53 } 54 55 /// Parses a string into a future value, while tracking the depth of the data. 56 #[inline] 57 fn parse_internal(string: &str, depth: usize) -> ParserResult<'_, Self> { 58 // Ensure that the depth is within the maximum limit. 59 // Note: `N::MAX_DATA_DEPTH` is an upper bound on the number of nested futures. 60 // The true maximum is defined by `Transaction::<N>::MAX_TRANSITIONS`, however, that object is not accessible in this crate. 61 // In practice, `MAX_DATA_DEPTH` is 32, while `MAX_TRANSITIONS` is 31. 62 if depth > N::MAX_DATA_DEPTH { 63 return map_res(take(0usize), |_| { 64 Err(error(format!("Found a future that exceeds maximum data depth ({})", N::MAX_DATA_DEPTH))) 65 })(string); 66 } 67 // Parse the whitespace and comments from the string. 68 let (string, _) = Sanitizer::parse(string)?; 69 // Parse the "{" from the string. 70 let (string, _) = tag("{")(string)?; 71 72 // Parse the whitespace and comments from the string. 73 let (string, _) = Sanitizer::parse(string)?; 74 // Parse the "program_id" from the string. 75 let (string, _) = tag("program_id")(string)?; 76 // Parse the whitespace from the string. 77 let (string, _) = Sanitizer::parse_whitespaces(string)?; 78 // Parse the ":" from the string. 79 let (string, _) = tag(":")(string)?; 80 // Parse the whitespace from the string. 81 let (string, _) = Sanitizer::parse_whitespaces(string)?; 82 // Parse the program ID from the string. 83 let (string, program_id) = ProgramID::parse(string)?; 84 // Parse the whitespace from the string. 85 let (string, _) = Sanitizer::parse_whitespaces(string)?; 86 // Parse the "," from the string. 87 let (string, _) = tag(",")(string)?; 88 89 // Parse the whitespace and comments from the string. 90 let (string, _) = Sanitizer::parse(string)?; 91 // Parse the "function_name" from the string. 92 let (string, _) = tag("function_name")(string)?; 93 // Parse the whitespace from the string. 94 let (string, _) = Sanitizer::parse_whitespaces(string)?; 95 // Parse the ":" from the string. 96 let (string, _) = tag(":")(string)?; 97 // Parse the whitespace from the string. 98 let (string, _) = Sanitizer::parse_whitespaces(string)?; 99 // Parse the function name from the string. 100 let (string, function_name) = Identifier::parse(string)?; 101 // Parse the whitespace from the string. 102 let (string, _) = Sanitizer::parse_whitespaces(string)?; 103 // Parse the "," from the string. 104 let (string, _) = tag(",")(string)?; 105 106 // Parse the whitespace and comments from the string. 107 let (string, _) = Sanitizer::parse(string)?; 108 // Parse the "arguments" from the string. 109 let (string, _) = tag("arguments")(string)?; 110 // Parse the whitespace from the string. 111 let (string, _) = Sanitizer::parse_whitespaces(string)?; 112 // Parse the ":" from the string. 113 let (string, _) = tag(":")(string)?; 114 // Parse the whitespace from the string. 115 let (string, _) = Sanitizer::parse_whitespaces(string)?; 116 // Parse the arguments from the string. 117 let (string, arguments) = Self::parse_arguments(string, depth)?; 118 119 // Parse the whitespace and comments from the string. 120 let (string, _) = Sanitizer::parse(string)?; 121 // Parse the "}" from the string. 122 let (string, _) = tag("}")(string)?; 123 124 Ok((string, Self::new(program_id, function_name, arguments))) 125 } 126 } 127 128 impl<N: Network> FromStr for Future<N> { 129 type Err = Error; 130 131 /// Returns a future from a string literal. 132 fn from_str(string: &str) -> Result<Self> { 133 match Self::parse(string) { 134 Ok((remainder, object)) => { 135 // Ensure the remainder is empty. 136 ensure!(remainder.is_empty(), "Failed to parse string. Found invalid character in: \"{remainder}\""); 137 // Return the object. 138 Ok(object) 139 } 140 Err(error) => bail!("Failed to parse string. {error}"), 141 } 142 } 143 } 144 145 impl<N: Network> Debug for Future<N> { 146 /// Prints the future as a string. 147 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 148 Display::fmt(self, f) 149 } 150 } 151 152 impl<N: Network> Display for Future<N> { 153 /// Prints the future as a string. 154 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 155 self.fmt_internal(f, 0) 156 } 157 } 158 159 impl<N: Network> Future<N> { 160 /// Prints the future with the given indentation depth. 161 fn fmt_internal(&self, f: &mut Formatter, depth: usize) -> fmt::Result { 162 /// The number of spaces to indent. 163 const INDENT: usize = 2; 164 165 // Print the opening brace. 166 write!(f, "{{")?; 167 168 // Print the program ID. 169 write!( 170 f, 171 "\n{:indent$}program_id: {program_id},", 172 "", 173 indent = (depth + 1) * INDENT, 174 program_id = self.program_id() 175 )?; 176 // Print the function name. 177 write!( 178 f, 179 "\n{:indent$}function_name: {function_name},", 180 "", 181 indent = (depth + 1) * INDENT, 182 function_name = self.function_name() 183 )?; 184 // Print the arguments. 185 // If the arguments are empty, print an empty array. 186 if self.arguments.is_empty() { 187 write!(f, "\n{:indent$}arguments: []", "", indent = (depth + 1) * INDENT)?; 188 } else { 189 write!(f, "\n{:indent$}arguments: [", "", indent = (depth + 1) * INDENT)?; 190 self.arguments.iter().enumerate().try_for_each(|(i, argument)| { 191 match argument { 192 Argument::Plaintext(plaintext) => match i == self.arguments.len() - 1 { 193 true => { 194 // Print the last argument without a comma. 195 write!( 196 f, 197 "\n{:indent$}{plaintext}", 198 "", 199 indent = (depth + 2) * INDENT, 200 plaintext = plaintext 201 ) 202 } 203 // Print the argument with a comma. 204 false => { 205 write!( 206 f, 207 "\n{:indent$}{plaintext},", 208 "", 209 indent = (depth + 2) * INDENT, 210 plaintext = plaintext 211 ) 212 } 213 }, 214 Argument::Future(future) => { 215 // Print a newline. 216 write!(f, "\n{:indent$}", "", indent = (depth + 2) * INDENT)?; 217 // Print the argument. 218 future.fmt_internal(f, depth + 2)?; 219 // Print the closing brace. 220 match i == self.arguments.len() - 1 { 221 // Print the last member without a comma. 222 true => write!(f, "\n{:indent$}", "", indent = (depth + 1) * INDENT), 223 // Print the member with a comma. 224 false => write!(f, ","), 225 } 226 } 227 } 228 })?; 229 // Print the closing bracket. 230 write!(f, "\n{:indent$}]", "", indent = (depth + 1) * INDENT)?; 231 } 232 233 // Print the closing brace. 234 write!(f, "\n{:indent$}}}", "", indent = depth * INDENT) 235 } 236 } 237 238 #[cfg(test)] 239 mod tests { 240 use super::*; 241 use alphavm_console_network::MainnetV0; 242 243 type CurrentNetwork = MainnetV0; 244 245 #[test] 246 fn test_parse_future() -> Result<()> { 247 // No argument case. 248 let expected = r"{ 249 program_id: credits.alpha, 250 function_name: transfer, 251 arguments: [] 252 }"; 253 let (remainder, candidate) = 254 Future::<CurrentNetwork>::parse("{ program_id: credits.alpha, function_name: transfer, arguments: [] }")?; 255 assert!(remainder.is_empty()); 256 assert_eq!(expected, candidate.to_string()); 257 assert_eq!("", remainder); 258 259 // Literal arguments. 260 let expected = r"{ 261 program_id: credits.alpha, 262 function_name: transfer_public_to_private, 263 arguments: [ 264 ax150w2lvhdzychwvzu54ys5zas7tm5s0ycdyw563pms83g9u0vucgqe5fs5w, 265 100000000u64 266 ] 267 }"; 268 let (remainder, candidate) = Future::<CurrentNetwork>::parse( 269 "{ program_id: credits.alpha, function_name: transfer_public_to_private, arguments: [ ax150w2lvhdzychwvzu54ys5zas7tm5s0ycdyw563pms83g9u0vucgqe5fs5w, 100000000u64 ] }", 270 )?; 271 assert!(remainder.is_empty()); 272 assert_eq!(expected, candidate.to_string()); 273 assert_eq!("", remainder); 274 275 Ok(()) 276 } 277 278 #[test] 279 fn test_deeply_nested_future() { 280 // A helper function to iteratively create a deeply nested future. 281 fn create_nested_future(depth: usize) -> String { 282 // Define the base case. 283 let root = r"{ 284 program_id: foo.alpha, 285 function_name: bar, 286 arguments: [] 287 }"; 288 // Define the prefix and suffix for the nested future. 289 let prefix = r"{ 290 program_id: foo.alpha, 291 function_name: bar, 292 arguments: [" 293 .repeat(depth); 294 let suffix = r"]}".repeat(depth); 295 // Concatenate the prefix, root, and suffix to create the nested future. 296 format!("{prefix}{root}{suffix}") 297 } 298 299 // A helper function to test the parsing of a deeply nested future. 300 fn run_test(depth: usize, expected_error: bool) { 301 // Create the nested future string. 302 let nested_future_string = create_nested_future(depth); 303 // Parse the nested future. 304 let result = Future::<CurrentNetwork>::parse(&nested_future_string); 305 // Check if the result is an error. 306 match expected_error { 307 true => { 308 assert!(result.is_err()); 309 return; 310 } 311 false => assert!(result.is_ok()), 312 }; 313 // Unwrap the result. 314 let (remainder, candidate) = result.unwrap(); 315 // Ensure the remainder is empty. 316 assert!( 317 remainder.is_empty(), 318 "Failed to parse deeply nested future. Found invalid character in: \"{remainder}\"" 319 ); 320 // Strip the expected string of whitespace. 321 let expected = nested_future_string.replace("\n", "").replace(" ", "").replace("\t", ""); 322 // Strip the candidate string of whitespace. 323 let candidate_str = candidate.to_string().replace("\n", "").replace(" ", "").replace("\t", ""); 324 // Ensure the expected and candidate strings are equal. 325 assert_eq!(expected, candidate_str, "Expected: {expected}, Candidate: {candidate_str}"); 326 } 327 328 // Initialize a set of depths to test. 329 let mut depths = (0usize..100).collect_vec(); 330 depths.extend((100..1000).step_by(100)); 331 depths.extend((1000..10000).step_by(1000)); 332 depths.extend((10000..100000).step_by(10000)); 333 334 // For each depth, test the parsing of a deeply nested future. 335 for depth in depths { 336 run_test(depth, depth > CurrentNetwork::MAX_DATA_DEPTH); 337 } 338 } 339 }