from_field.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<E: Environment, I: IntegerType> FromField for Integer<E, I> { 22 type Field = Field<E>; 23 24 /// Casts an integer from a base field. 25 /// 26 /// This method guarantees the following: 27 /// 1. If the field element is larger than the integer domain, then the operation will fail. 28 /// 2. If the field element is smaller than the integer domain, then the operation will succeed. 29 fn from_field(field: &Self::Field) -> Result<Self> { 30 // Note: We are reconstituting the integer from the base field. 31 // This is safe as the number of bits in the integer is less than the base field modulus, 32 // and thus will always fit within a single base field element. 33 debug_assert!(I::BITS < Field::<E>::size_in_bits() as u64); 34 35 // Convert the field element into bits. 36 let bits_le = field.to_bits_le(); 37 38 // Extract the integer bits from the field element, **without** a carry bit. 39 let (bits_le, zero_bits) = bits_le.split_at(Self::size_in_bits()); 40 41 // Ensure the unused upper bits are all zero. 42 ensure!(zero_bits.iter().all(|&bit| !bit), "Failed to convert field to integer: upper bits are not zero"); 43 44 // Return the integer. 45 Self::from_bits_le(bits_le) 46 } 47 } 48 49 #[cfg(test)] 50 mod tests { 51 use super::*; 52 use alphavm_console_network_environment::Console; 53 54 type CurrentEnvironment = Console; 55 56 const ITERATIONS: u64 = 10_000; 57 58 fn check_from_field<I: IntegerType>() -> Result<()> { 59 let mut rng = TestRng::default(); 60 61 for _ in 0..ITERATIONS { 62 // Sample a random integer. 63 let expected = Integer::<CurrentEnvironment, I>::rand(&mut rng); 64 65 // Perform the operation. 66 let candidate = Integer::from_field(&expected.to_field()?)?; 67 assert_eq!(expected, candidate); 68 69 // Sample a random field. 70 let expected = Field::<CurrentEnvironment>::rand(&mut rng); 71 // Determine the integer domain. 72 let integer_max = match I::type_name() { 73 "u8" | "i8" => Field::<CurrentEnvironment>::from_u8(u8::MAX), 74 "u16" | "i16" => Field::<CurrentEnvironment>::from_u16(u16::MAX), 75 "u32" | "i32" => Field::<CurrentEnvironment>::from_u32(u32::MAX), 76 "u64" | "i64" => Field::<CurrentEnvironment>::from_u64(u64::MAX), 77 "u128" | "i128" => Field::<CurrentEnvironment>::from_u128(u128::MAX), 78 _ => panic!("Unsupported integer type."), 79 }; 80 // Filter for field elements that exceed the integer domain. 81 if expected > integer_max { 82 // Perform the operation. 83 assert!(Integer::<_, I>::from_field(&expected).is_err()); 84 } else { 85 // Perform the operation. 86 assert!(Integer::<_, I>::from_field(&expected).is_ok()); 87 } 88 } 89 Ok(()) 90 } 91 92 #[test] 93 fn test_u8_from_field() -> Result<()> { 94 type I = u8; 95 check_from_field::<I>() 96 } 97 98 #[test] 99 fn test_i8_from_field() -> Result<()> { 100 type I = i8; 101 check_from_field::<I>() 102 } 103 104 #[test] 105 fn test_u16_from_field() -> Result<()> { 106 type I = u16; 107 check_from_field::<I>() 108 } 109 110 #[test] 111 fn test_i16_from_field() -> Result<()> { 112 type I = i16; 113 check_from_field::<I>() 114 } 115 116 #[test] 117 fn test_u32_from_field() -> Result<()> { 118 type I = u32; 119 check_from_field::<I>() 120 } 121 122 #[test] 123 fn test_i32_from_field() -> Result<()> { 124 type I = i32; 125 check_from_field::<I>() 126 } 127 128 #[test] 129 fn test_u64_from_field() -> Result<()> { 130 type I = u64; 131 check_from_field::<I>() 132 } 133 134 #[test] 135 fn test_i64_from_field() -> Result<()> { 136 type I = i64; 137 check_from_field::<I>() 138 } 139 140 #[test] 141 fn test_u128_from_field() -> Result<()> { 142 type I = u128; 143 check_from_field::<I>() 144 } 145 146 #[test] 147 fn test_i128_from_field() -> Result<()> { 148 type I = i128; 149 check_from_field::<I>() 150 } 151 }