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 Plaintext<N> { 22 /// Reads the plaintext from a buffer. 23 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> { 24 Self::read_le_internal(&mut reader, 0) 25 } 26 } 27 28 impl<N: Network> Plaintext<N> { 29 /// Reads the plaintext from a buffer, while tracking the depth of the data. 30 fn read_le_internal<R: Read>(mut reader: R, depth: usize) -> IoResult<Self> { 31 // Ensure that the depth is within the maximum limit. 32 if depth > N::MAX_DATA_DEPTH { 33 return Err(error(format!( 34 "Failed to deserialize plaintext: Depth exceeds maximum limit: {}", 35 N::MAX_DATA_DEPTH 36 ))); 37 } 38 // Read the index. 39 let index = u8::read_le(&mut reader)?; 40 // Read the plaintext. 41 let plaintext = match index { 42 0 => Self::Literal(Literal::read_le(&mut reader)?, Default::default()), 43 1 => { 44 // Read the number of members in the struct. 45 let num_members = u8::read_le(&mut reader)?; 46 // Read the members. 47 let mut members = IndexMap::with_capacity(num_members as usize); 48 for _ in 0..num_members { 49 // Read the identifier. 50 let identifier = Identifier::<N>::read_le(&mut reader)?; 51 // Read the plaintext value (in 2 steps to prevent infinite recursion). 52 let num_bytes = u16::read_le(&mut reader)?; 53 // Read the plaintext bytes. 54 let mut bytes = Vec::new(); 55 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?; 56 // Recover the plaintext value. 57 let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?; 58 // Add the member. 59 members.insert(identifier, plaintext); 60 } 61 // Return the struct. 62 Self::Struct(members, Default::default()) 63 } 64 2 => { 65 // Read the length of the array. 66 let num_elements = u32::read_le(&mut reader)?; 67 if num_elements as usize > N::MAX_ARRAY_ELEMENTS { 68 return Err(error("Failed to deserialize plaintext: Array exceeds maximum length")); 69 } 70 // Read the elements. 71 let mut elements = Vec::with_capacity(num_elements as usize); 72 for _ in 0..num_elements { 73 // Read the plaintext value (in 2 steps to prevent infinite recursion). 74 let num_bytes = u16::read_le(&mut reader)?; 75 // Read the plaintext bytes. 76 let mut bytes = Vec::new(); 77 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?; 78 // Recover the plaintext value. 79 let plaintext = Self::read_le_internal(&mut bytes.as_slice(), depth + 1)?; 80 // Add the element. 81 elements.push(plaintext); 82 } 83 // Return the array. 84 Self::Array(elements, Default::default()) 85 } 86 3.. => return Err(error(format!("Failed to decode plaintext variant {index}"))), 87 }; 88 Ok(plaintext) 89 } 90 } 91 92 impl<N: Network> ToBytes for Plaintext<N> { 93 /// Writes the plaintext to a buffer. 94 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> { 95 match self { 96 Self::Literal(literal, ..) => { 97 0u8.write_le(&mut writer)?; 98 literal.write_le(&mut writer) 99 } 100 Self::Struct(struct_, ..) => { 101 1u8.write_le(&mut writer)?; 102 103 // Write the number of members in the struct. 104 u8::try_from(struct_.len()).map_err(error)?.write_le(&mut writer)?; 105 106 // Write each member. 107 for (member_name, member_value) in struct_ { 108 // Write the member name. 109 member_name.write_le(&mut writer)?; 110 111 // Write the member value (performed in 2 steps to prevent infinite recursion). 112 let bytes = member_value.to_bytes_le().map_err(|e| error(e.to_string()))?; 113 // Write the number of bytes. 114 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?; 115 // Write the bytes. 116 bytes.write_le(&mut writer)?; 117 } 118 Ok(()) 119 } 120 Self::Array(array, ..) => { 121 2u8.write_le(&mut writer)?; 122 123 // Write the length of the array. 124 u32::try_from(array.len()).map_err(error)?.write_le(&mut writer)?; 125 126 // Write each element. 127 for element in array { 128 // Write the element (performed in 2 steps to prevent infinite recursion). 129 let bytes = element.to_bytes_le().map_err(error)?; 130 // Write the number of bytes. 131 u16::try_from(bytes.len()).map_err(error)?.write_le(&mut writer)?; 132 // Write the bytes. 133 bytes.write_le(&mut writer)?; 134 } 135 Ok(()) 136 } 137 } 138 } 139 } 140 141 #[cfg(test)] 142 mod tests { 143 use super::*; 144 use alphavm_console_network::MainnetV0; 145 146 type CurrentNetwork = MainnetV0; 147 148 const ITERATIONS: u32 = 1000; 149 150 fn check_bytes(expected: Plaintext<CurrentNetwork>) -> Result<()> { 151 // Check the byte representation. 152 let expected_bytes = expected.to_bytes_le()?; 153 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?); 154 Ok(()) 155 } 156 157 #[test] 158 fn test_bytes() -> Result<()> { 159 let rng = &mut TestRng::default(); 160 161 for _ in 0..ITERATIONS { 162 let private_key = alphavm_console_account::PrivateKey::<CurrentNetwork>::new(rng)?; 163 164 // Address 165 check_bytes(Plaintext::Literal( 166 Literal::<CurrentNetwork>::Address(Address::try_from(private_key)?), 167 Default::default(), 168 ))?; 169 // Boolean 170 check_bytes(Plaintext::Literal( 171 Literal::<CurrentNetwork>::Boolean(Boolean::new(Uniform::rand(rng))), 172 Default::default(), 173 ))?; 174 // Field 175 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Field(Uniform::rand(rng)), Default::default()))?; 176 // Group 177 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Group(Uniform::rand(rng)), Default::default()))?; 178 // I8 179 check_bytes(Plaintext::Literal( 180 Literal::<CurrentNetwork>::I8(I8::new(Uniform::rand(rng))), 181 Default::default(), 182 ))?; 183 // I16 184 check_bytes(Plaintext::Literal( 185 Literal::<CurrentNetwork>::I16(I16::new(Uniform::rand(rng))), 186 Default::default(), 187 ))?; 188 // I32 189 check_bytes(Plaintext::Literal( 190 Literal::<CurrentNetwork>::I32(I32::new(Uniform::rand(rng))), 191 Default::default(), 192 ))?; 193 // I64 194 check_bytes(Plaintext::Literal( 195 Literal::<CurrentNetwork>::I64(I64::new(Uniform::rand(rng))), 196 Default::default(), 197 ))?; 198 // I128 199 check_bytes(Plaintext::Literal( 200 Literal::<CurrentNetwork>::I128(I128::new(Uniform::rand(rng))), 201 Default::default(), 202 ))?; 203 // U8 204 check_bytes(Plaintext::Literal( 205 Literal::<CurrentNetwork>::U8(U8::new(Uniform::rand(rng))), 206 Default::default(), 207 ))?; 208 // U16 209 check_bytes(Plaintext::Literal( 210 Literal::<CurrentNetwork>::U16(U16::new(Uniform::rand(rng))), 211 Default::default(), 212 ))?; 213 // U32 214 check_bytes(Plaintext::Literal( 215 Literal::<CurrentNetwork>::U32(U32::new(Uniform::rand(rng))), 216 Default::default(), 217 ))?; 218 // U64 219 check_bytes(Plaintext::Literal( 220 Literal::<CurrentNetwork>::U64(U64::new(Uniform::rand(rng))), 221 Default::default(), 222 ))?; 223 // U128 224 check_bytes(Plaintext::Literal( 225 Literal::<CurrentNetwork>::U128(U128::new(Uniform::rand(rng))), 226 Default::default(), 227 ))?; 228 // Scalar 229 check_bytes(Plaintext::Literal(Literal::<CurrentNetwork>::Scalar(Uniform::rand(rng)), Default::default()))?; 230 // String 231 check_bytes(Plaintext::Literal( 232 Literal::<CurrentNetwork>::String(StringType::rand(rng)), 233 Default::default(), 234 ))?; 235 } 236 237 // Check the struct manually. 238 let expected = Plaintext::<CurrentNetwork>::from_str( 239 "{ owner: ax150w2lvhdzychwvzu54ys5zas7tm5s0ycdyw563pms83g9u0vucgqe5fs5w, token_amount: 100u64 }", 240 )?; 241 242 // Check the byte representation. 243 let expected_bytes = expected.to_bytes_le()?; 244 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?); 245 246 // Check the array manually. 247 let expected = Plaintext::<CurrentNetwork>::from_str("[ 1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8 ]")?; 248 249 // Check the byte representation. 250 let expected_bytes = expected.to_bytes_le()?; 251 assert_eq!(expected, Plaintext::read_le(&expected_bytes[..])?); 252 253 Ok(()) 254 } 255 256 // A helper function to get the depth of the plaintext. 257 fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize { 258 match plaintext { 259 Plaintext::Literal(_, _) => 0, 260 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1, 261 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1, 262 } 263 } 264 265 #[test] 266 fn test_deeply_nested_plaintext() { 267 // Creates a nested array-like `Plaintext` structure by wrapping a root value `depth` times. 268 fn create_nested_array(depth: usize, root: impl Display) -> Vec<u8> { 269 // Start from the innermost value. 270 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap(); 271 // Reverse the bytes. 272 result.reverse(); 273 // Build up the structure in reverse. 274 for _ in 0..depth { 275 // Write the size of the object in bytes in reverse. 276 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap(); 277 length.reverse(); 278 result.extend(length); 279 // Write the number of elements in the array in reverse. 280 let mut num_elements = 1u32.to_bytes_le().unwrap(); 281 num_elements.reverse(); 282 result.extend(num_elements); 283 // Write the plaintext variant in reverse. 284 let mut variant = 2u8.to_bytes_le().unwrap(); 285 variant.reverse(); 286 result.extend(variant); 287 } 288 // Reverse the result to get the correct order. 289 result.reverse(); 290 result 291 } 292 293 // Creates a nested struct-like `Plaintext` structure by wrapping a root value `depth` times. 294 fn create_nested_struct(depth: usize, root: impl Display) -> Vec<u8> { 295 // Start from the innermost value. 296 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap(); 297 // Reverse the bytes. 298 result.reverse(); 299 // Build up the structure in reverse. 300 for _ in 0..depth { 301 // Write the size of the object in bytes in reverse. 302 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap(); 303 length.reverse(); 304 result.extend(length); 305 // Write the member name in reverse. 306 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap(); 307 member_name.reverse(); 308 result.extend(member_name); 309 // Write the number of members in the struct in reverse. 310 let mut num_members = 1u8.to_bytes_le().unwrap(); 311 num_members.reverse(); 312 result.extend(num_members); 313 // Write the plaintext variant in reverse. 314 let mut variant = 1u8.to_bytes_le().unwrap(); 315 variant.reverse(); 316 result.extend(variant); 317 } 318 // Reverse the result to get the correct order. 319 result.reverse(); 320 result 321 } 322 323 // Creates a nested `Plaintext` structure with alternating array and struct wrappers. 324 fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<u8> { 325 // Start from the innermost value. 326 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bytes_le().unwrap(); 327 // Reverse the bytes. 328 result.reverse(); 329 // Build up the structure in reverse. 330 for i in 0..depth { 331 // Write the size of the object in bytes in reverse. 332 let mut length = (u16::try_from(result.len()).unwrap()).to_bytes_le().unwrap(); 333 length.reverse(); 334 result.extend(length); 335 // Determine the type of the wrapper (array or struct) and handle accordingly. 336 if i % 2 == 0 { 337 // Write the number of elements in the array in reverse. 338 let mut num_elements = 1u32.to_bytes_le().unwrap(); 339 num_elements.reverse(); 340 result.extend(num_elements); 341 // Write the plaintext variant for array in reverse. 342 let mut variant = 2u8.to_bytes_le().unwrap(); 343 variant.reverse(); 344 result.extend(variant); 345 } else { 346 // Write the member name in reverse. 347 let mut member_name = 348 Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bytes_le().unwrap(); 349 member_name.reverse(); 350 result.extend(member_name); 351 // Write the number of members in the struct in reverse. 352 let mut num_members = 1u8.to_bytes_le().unwrap(); 353 num_members.reverse(); 354 result.extend(num_members); 355 // Write the plaintext variant for struct in reverse. 356 let mut variant = 1u8.to_bytes_le().unwrap(); 357 variant.reverse(); 358 result.extend(variant); 359 } 360 } 361 // Reverse the result to get the correct order. 362 result.reverse(); 363 result 364 } 365 366 // A helper function to run the test. 367 fn run_test(expected_depth: usize, input: Vec<u8>, expected_error: bool) { 368 // Parse the input string. 369 let result = Plaintext::<CurrentNetwork>::read_le(&*input); 370 // Check if the result is an error. 371 match expected_error { 372 true => { 373 assert!(result.is_err()); 374 return; 375 } 376 false => assert!(result.is_ok()), 377 }; 378 // Unwrap the result. 379 let candidate = result.unwrap(); 380 // Check if the candidate is equal to the input. 381 assert_eq!(input, candidate.to_bytes_le().unwrap()); 382 // Check if the candidate is equal to the expected depth. 383 assert_eq!(get_depth(&candidate), expected_depth); 384 } 385 386 // Initialize a sequence of depths to check. 387 // Note that 6500 is approximate maximum depth that can be constructed in this test. 388 let mut depths = (0usize..100).collect_vec(); 389 depths.extend((100..6500).step_by(100)); 390 391 // Test deeply nested arrays with different literal types. 392 for i in depths.iter().copied() { 393 run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 394 run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 395 run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 396 run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 397 } 398 399 // Test deeply nested structs with different literal types. 400 for i in depths.iter().copied() { 401 run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 402 run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 403 run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 404 run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 405 } 406 407 // Test alternating nested arrays and structs. 408 for i in depths.iter().copied() { 409 run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 410 run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 411 run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 412 run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 413 } 414 } 415 }