from_bits.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> FromBits for Plaintext<N> { 19 /// Initializes a new plaintext from a list of little-endian bits *without* trailing zeros. 20 fn from_bits_le(bits_le: &[bool]) -> Result<Self> { 21 Self::from_bits_le_internal(bits_le, 0) 22 } 23 24 /// Initializes a new plaintext from a list of big-endian bits *without* trailing zeros. 25 fn from_bits_be(bits_be: &[bool]) -> Result<Self> { 26 Self::from_bits_be_internal(bits_be, 0) 27 } 28 } 29 30 impl<N: Network> Plaintext<N> { 31 /// Initializes a new plaintext from a list of little-endian bits *without* trailing zeros, while the depth of the data. 32 fn from_bits_le_internal(bits_le: &[bool], depth: usize) -> Result<Self> { 33 // Ensure that the depth is within the maximum limit. 34 if depth > N::MAX_DATA_DEPTH { 35 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH) 36 } 37 38 let bits = bits_le; 39 40 // The starting index used to create subsequent subslices of the `bits` slice. 41 let mut index = 0; 42 43 // Helper function to get the next n bits as a slice. 44 let mut next_bits = |n: usize| -> Result<&[bool]> { 45 // Safely procure a subslice with the length `n` starting at `index`. 46 let subslice = bits.get(index..index + n); 47 // Check if the range is within bounds. 48 if let Some(next_bits) = subslice { 49 // Move the starting index. 50 index += n; 51 // Return the subslice. 52 Ok(next_bits) 53 } else { 54 bail!("Insufficient bits"); 55 } 56 }; 57 58 let variant = next_bits(2)?; 59 let variant = [variant[0], variant[1]]; 60 61 // Literal 62 if variant == PlaintextType::<N>::LITERAL_PREFIX_BITS { 63 let literal_variant = u8::from_bits_le(next_bits(8)?)?; 64 let literal_size = u16::from_bits_le(next_bits(16)?)?; 65 let literal = Literal::from_bits_le(literal_variant, next_bits(literal_size as usize)?)?; 66 67 // Cache the plaintext bits, and return the literal. 68 Ok(Self::Literal(literal, bits_le.to_vec().into())) 69 } 70 // Struct 71 else if variant == PlaintextType::<N>::STRUCT_PREFIX_BITS { 72 let num_members = u8::from_bits_le(next_bits(8)?)?; 73 if num_members as usize > N::MAX_STRUCT_ENTRIES { 74 bail!("Struct exceeds maximum of entries."); 75 } 76 77 let mut members = IndexMap::with_capacity(num_members as usize); 78 for _ in 0..num_members { 79 let identifier_size = u8::from_bits_le(next_bits(8)?)?; 80 let identifier = Identifier::from_bits_le(next_bits(identifier_size as usize)?)?; 81 82 let member_size = u16::from_bits_le(next_bits(16)?)?; 83 let value = Plaintext::from_bits_le_internal(next_bits(member_size as usize)?, depth + 1)?; 84 85 if members.insert(identifier, value).is_some() { 86 bail!("Duplicate identifier in struct."); 87 } 88 } 89 90 // Cache the plaintext bits, and return the struct. 91 Ok(Self::Struct(members, bits_le.to_vec().into())) 92 } 93 // Array 94 else if variant == PlaintextType::<N>::ARRAY_PREFIX_BITS { 95 let num_elements = u32::from_bits_le(next_bits(32)?)?; 96 if num_elements as usize > N::MAX_ARRAY_ELEMENTS { 97 bail!("Array exceeds maximum of elements."); 98 } 99 100 let mut elements = Vec::with_capacity(num_elements as usize); 101 for _ in 0..num_elements { 102 let element_size = u16::from_bits_le(next_bits(16)?)?; 103 let element = Plaintext::from_bits_le_internal(next_bits(element_size as usize)?, depth + 1)?; 104 105 elements.push(element); 106 } 107 108 // Cache the plaintext bits, and return the array. 109 Ok(Self::Array(elements, bits_le.to_vec().into())) 110 } 111 // Unknown variant. 112 else { 113 bail!("Unknown plaintext variant - {variant:?}"); 114 } 115 } 116 117 /// Initializes a new plaintext from a list of big-endian bits *without* trailing zeros, while tracking the depth of the data. 118 fn from_bits_be_internal(bits_be: &[bool], depth: usize) -> Result<Self> { 119 // Ensure that the depth is within the maximum limit. 120 if depth > N::MAX_DATA_DEPTH { 121 bail!("Plaintext depth exceeds maximum limit: {}", N::MAX_DATA_DEPTH) 122 } 123 124 let bits = bits_be; 125 126 // The starting index used to create subsequent subslices of the `bits` slice. 127 let mut index = 0; 128 129 // Helper function to get the next n bits as a slice. 130 let mut next_bits = |n: usize| -> Result<&[bool]> { 131 // Safely procure a subslice with the length `n` starting at `index`. 132 let subslice = bits.get(index..index + n); 133 // Check if the range is within bounds. 134 if let Some(next_bits) = subslice { 135 // Move the starting index. 136 index += n; 137 // Return the subslice. 138 Ok(next_bits) 139 } else { 140 bail!("Insufficient bits"); 141 } 142 }; 143 144 let variant = next_bits(2)?; 145 let variant = [variant[0], variant[1]]; 146 147 // Literal 148 if variant == PlaintextType::<N>::LITERAL_PREFIX_BITS { 149 let literal_variant = u8::from_bits_be(next_bits(8)?)?; 150 let literal_size = u16::from_bits_be(next_bits(16)?)?; 151 let literal = Literal::from_bits_be(literal_variant, next_bits(literal_size as usize)?)?; 152 153 // Cache the plaintext bits, and return the literal. 154 Ok(Self::Literal(literal, bits_be.to_vec().into())) 155 } 156 // Struct 157 else if variant == PlaintextType::<N>::STRUCT_PREFIX_BITS { 158 let num_members = u8::from_bits_be(next_bits(8)?)?; 159 if num_members as usize > N::MAX_STRUCT_ENTRIES { 160 bail!("Struct exceeds maximum of entries."); 161 } 162 let mut members = IndexMap::with_capacity(num_members as usize); 163 for _ in 0..num_members { 164 let identifier_size = u8::from_bits_be(next_bits(8)?)?; 165 let identifier = Identifier::from_bits_be(next_bits(identifier_size as usize)?)?; 166 let member_size = u16::from_bits_be(next_bits(16)?)?; 167 let value = Plaintext::from_bits_be_internal(next_bits(member_size as usize)?, depth + 1)?; 168 if members.insert(identifier, value).is_some() { 169 bail!("Duplicate identifier in struct."); 170 } 171 } 172 173 // Cache the plaintext bits, and return the struct. 174 Ok(Self::Struct(members, bits_be.to_vec().into())) 175 } 176 // Array 177 else if variant == PlaintextType::<N>::ARRAY_PREFIX_BITS { 178 let num_elements = u32::from_bits_be(next_bits(32)?)?; 179 if num_elements as usize > N::MAX_ARRAY_ELEMENTS { 180 bail!("Array exceeds maximum of elements."); 181 } 182 183 let mut elements = Vec::with_capacity(num_elements as usize); 184 for _ in 0..num_elements { 185 let element_size = u16::from_bits_be(next_bits(16)?)?; 186 let element = Plaintext::from_bits_be_internal(next_bits(element_size as usize)?, depth + 1)?; 187 188 elements.push(element); 189 } 190 191 // Cache the plaintext bits, and return the array. 192 Ok(Self::Array(elements, bits_be.to_vec().into())) 193 } 194 // Unknown variant. 195 else { 196 bail!("Unknown plaintext variant - {variant:?}"); 197 } 198 } 199 } 200 201 #[cfg(test)] 202 mod tests { 203 use super::*; 204 use alphavm_console_network::MainnetV0; 205 206 type CurrentNetwork = MainnetV0; 207 208 // A helper function to get the depth of the plaintext. 209 fn get_depth(plaintext: &Plaintext<CurrentNetwork>) -> usize { 210 match plaintext { 211 Plaintext::Literal(_, _) => 0, 212 Plaintext::Struct(members, _) => members.values().map(get_depth).max().unwrap_or(0) + 1, 213 Plaintext::Array(elements, _) => elements.iter().map(get_depth).max().unwrap_or(0) + 1, 214 } 215 } 216 217 #[test] 218 fn test_deeply_nested_plaintext_bits_le() { 219 // Creates a nested array-like `Plaintext` structure by wrapping a root value `depth` times. 220 fn create_nested_array(depth: usize, root: impl Display) -> Vec<bool> { 221 // Start from the innermost value. 222 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le(); 223 // Reverse the bytes. 224 result.reverse(); 225 // Build up the structure in reverse. 226 for _ in 0..depth { 227 // Write the size of the object in bits in reverse. 228 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le(); 229 length.reverse(); 230 result.extend(length); 231 // Write the number of elements in the array in reverse. 232 let mut num_elements = 1u32.to_bits_le(); 233 num_elements.reverse(); 234 result.extend(num_elements); 235 // Write the plaintext variant in reverse. 236 result.extend([false, true]); 237 } 238 // Reverse the result to get the correct order. 239 result.reverse(); 240 result 241 } 242 243 // Creates a nested struct-like `Plaintext` structure by wrapping a root value `depth` times. 244 fn create_nested_struct(depth: usize, root: impl Display) -> Vec<bool> { 245 // Start from the innermost value. 246 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le(); 247 // Reverse the bytes. 248 result.reverse(); 249 // Build up the structure in reverse. 250 for _ in 0..depth { 251 // Write the size of the object in bits in reverse. 252 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le(); 253 length.reverse(); 254 result.extend(length); 255 // Write the member name in reverse. 256 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le(); 257 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le(); 258 member_name.reverse(); 259 result.extend(member_name); 260 // Write the length of the member name in reverse. 261 member_name_length.reverse(); 262 result.extend(member_name_length); 263 // Write the number of members in the struct in reverse. 264 let mut num_members = 1u8.to_bits_le(); 265 num_members.reverse(); 266 result.extend(num_members); 267 // Write the plaintext variant in reverse. 268 result.extend([true, false]); 269 } 270 // Reverse the result to get the correct order. 271 result.reverse(); 272 result 273 } 274 275 // Creates a nested `Plaintext` structure with alternating array and struct wrappers. 276 fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<bool> { 277 // Start from the innermost value. 278 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_le(); 279 // Reverse the bytes. 280 result.reverse(); 281 // Build up the structure in reverse. 282 for i in 0..depth { 283 // Write the size of the object in bits in reverse. 284 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_le(); 285 length.reverse(); 286 result.extend(length); 287 // Determine the type of the wrapper (array or struct) and handle accordingly. 288 if i % 2 == 0 { 289 // Write the number of elements in the array in reverse. 290 let mut num_elements = 1u32.to_bits_le(); 291 num_elements.reverse(); 292 result.extend(num_elements); 293 // Write the plaintext variant for array in reverse. 294 result.extend([false, true]); 295 } else { 296 // Write the member name in reverse. 297 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_le(); 298 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_le(); 299 member_name.reverse(); 300 result.extend(member_name); 301 // Write the member name length in reverse. 302 member_name_length.reverse(); 303 result.extend(member_name_length); 304 // Write the number of members in the struct in reverse. 305 let mut num_members = 1u8.to_bits_le(); 306 num_members.reverse(); 307 result.extend(num_members); 308 // Write the plaintext variant for struct in reverse. 309 result.extend([true, false]); 310 } 311 } 312 // Reverse the result to get the correct order. 313 result.reverse(); 314 result 315 } 316 317 // A helper function to run the test. 318 fn run_test(expected_depth: usize, input: Vec<bool>, expected_error: bool) { 319 // Parse the input string. 320 let result = Plaintext::<CurrentNetwork>::from_bits_le(&input); 321 // Check if the result is an error. 322 match expected_error { 323 true => { 324 assert!(result.is_err()); 325 return; 326 } 327 false => assert!(result.is_ok()), 328 }; 329 // Unwrap the result. 330 let candidate = result.unwrap(); 331 // Check if the candidate is equal to the input. 332 assert_eq!(input, candidate.to_bits_le()); 333 // Check if the depth of the candidate is equal to the expected depth. 334 assert_eq!(get_depth(&candidate), expected_depth); 335 } 336 337 // Initialize a sequence of depths to check. 338 // Note that 890 is approximate maximum depth that can be constructed in this test. 339 let mut depths = (0usize..100).collect_vec(); 340 depths.extend((100..890).step_by(10)); 341 342 // Test deeply nested arrays with different literal types. 343 for i in depths.iter().copied() { 344 run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 345 run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 346 run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 347 run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 348 } 349 350 // Test deeply nested structs with different literal types. 351 for i in depths.iter().copied() { 352 run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 353 run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 354 run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 355 run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 356 } 357 358 // Test alternating nested arrays and structs. 359 for i in depths.iter().copied() { 360 run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 361 run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 362 run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 363 run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 364 } 365 } 366 367 #[test] 368 fn test_deeply_nested_plaintext_bits_be() { 369 // Creates a nested array-like `Plaintext` structure by wrapping a root value `depth` times. 370 fn create_nested_array(depth: usize, root: impl Display) -> Vec<bool> { 371 // Start from the innermost value. 372 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be(); 373 // Reverse the bits. 374 result.reverse(); 375 // Build up the structure in reverse. 376 for _ in 0..depth { 377 // Write the size of the object in bits in reverse. 378 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be(); 379 length.reverse(); 380 result.extend(length); 381 // Write the number of elements in the array in reverse. 382 let mut num_elements = 1u32.to_bits_be(); 383 num_elements.reverse(); 384 result.extend(num_elements); 385 // Write the plaintext variant in reverse. 386 result.extend([false, true]); 387 } 388 // Reverse the result to get the correct order. 389 result.reverse(); 390 result 391 } 392 393 // Creates a nested struct-like `Plaintext` structure by wrapping a root value `depth` times. 394 fn create_nested_struct(depth: usize, root: impl Display) -> Vec<bool> { 395 // Start from the innermost value. 396 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be(); 397 // Reverse the bytes. 398 result.reverse(); 399 // Build up the structure in reverse. 400 for _ in 0..depth { 401 // Write the size of the object in bits in reverse. 402 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be(); 403 length.reverse(); 404 result.extend(length); 405 // Write the member name in reverse. 406 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be(); 407 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be(); 408 member_name.reverse(); 409 result.extend(member_name); 410 // Write the length of the member name in reverse. 411 member_name_length.reverse(); 412 result.extend(member_name_length); 413 // Write the number of members in the struct in reverse. 414 let mut num_members = 1u8.to_bits_be(); 415 num_members.reverse(); 416 result.extend(num_members); 417 // Write the plaintext variant in reverse. 418 result.extend([true, false]); 419 } 420 // Reverse the result to get the correct order. 421 result.reverse(); 422 result 423 } 424 425 // Creates a nested `Plaintext` structure with alternating array and struct wrappers. 426 fn create_alternated_nested(depth: usize, root: impl Display) -> Vec<bool> { 427 // Start from the innermost value. 428 let mut result = Plaintext::<CurrentNetwork>::from_str(&root.to_string()).unwrap().to_bits_be(); 429 // Reverse the bytes. 430 result.reverse(); 431 // Build up the structure in reverse. 432 for i in 0..depth { 433 // Write the size of the object in bits in reverse. 434 let mut length = (u16::try_from(result.len()).unwrap()).to_bits_be(); 435 length.reverse(); 436 result.extend(length); 437 // Determine the type of the wrapper (array or struct) and handle accordingly. 438 if i % 2 == 0 { 439 // Write the number of elements in the array in reverse. 440 let mut num_elements = 1u32.to_bits_be(); 441 num_elements.reverse(); 442 result.extend(num_elements); 443 // Write the plaintext variant for array in reverse. 444 result.extend([false, true]); 445 } else { 446 // Write the member name in reverse. 447 let mut member_name = Identifier::<CurrentNetwork>::from_str("inner").unwrap().to_bits_be(); 448 let mut member_name_length = u8::try_from(member_name.len()).unwrap().to_bits_be(); 449 member_name.reverse(); 450 result.extend(member_name); 451 // Write the member name length in reverse. 452 member_name_length.reverse(); 453 result.extend(member_name_length); 454 // Write the number of members in the struct in reverse. 455 let mut num_members = 1u8.to_bits_be(); 456 num_members.reverse(); 457 result.extend(num_members); 458 // Write the plaintext variant for struct in reverse. 459 result.extend([true, false]); 460 } 461 } 462 // Reverse the result to get the correct order. 463 result.reverse(); 464 result 465 } 466 467 // A helper function to run the test. 468 fn run_test(expected_depth: usize, input: Vec<bool>, expected_error: bool) { 469 // Parse the input string. 470 let result = Plaintext::<CurrentNetwork>::from_bits_be(&input); 471 // Check if the result is an error. 472 match expected_error { 473 true => { 474 assert!(result.is_err()); 475 return; 476 } 477 false => assert!(result.is_ok()), 478 }; 479 // Unwrap the result. 480 let candidate = result.unwrap(); 481 // Check if the candidate is equal to the input. 482 assert_eq!(input, candidate.to_bits_be()); 483 // Check if the depth of the candidate is equal to the expected depth. 484 assert_eq!(get_depth(&candidate), expected_depth); 485 } 486 487 // Initialize a sequence of depths to check. 488 // Note that 890 is approximate maximum depth that can be constructed in this test. 489 let mut depths = (0usize..100).collect_vec(); 490 depths.extend((100..890).step_by(10)); 491 492 // Test deeply nested arrays with different literal types. 493 for i in depths.iter().copied() { 494 run_test(i, create_nested_array(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 495 run_test(i, create_nested_array(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 496 run_test(i, create_nested_array(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 497 run_test(i, create_nested_array(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 498 } 499 500 // Test deeply nested structs with different literal types. 501 for i in depths.iter().copied() { 502 run_test(i, create_nested_struct(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 503 run_test(i, create_nested_struct(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 504 run_test(i, create_nested_struct(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 505 run_test(i, create_nested_struct(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 506 } 507 508 // Test alternating nested arrays and structs. 509 for i in depths.iter().copied() { 510 run_test(i, create_alternated_nested(i, "false"), i > CurrentNetwork::MAX_DATA_DEPTH); 511 run_test(i, create_alternated_nested(i, "1u8"), i > CurrentNetwork::MAX_DATA_DEPTH); 512 run_test(i, create_alternated_nested(i, "0u128"), i > CurrentNetwork::MAX_DATA_DEPTH); 513 run_test(i, create_alternated_nested(i, "10field"), i > CurrentNetwork::MAX_DATA_DEPTH); 514 } 515 } 516 }