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