|  | 
| 13 | 13 | //! assert!(hash == [0x185f8db3, 0x2271fe25, 0xf561a6fc, 0x938b2e26, 0x4306ec30, 0x4eda5180, | 
| 14 | 14 | //! 0x7d17648, 0x26381969]); | 
| 15 | 15 | //! ``` | 
|  | 16 | +#[feature("byte-span")] | 
|  | 17 | +use core::byte_array::ToByteSpanTrait; | 
|  | 18 | +#[feature("bounded-int-utils")] | 
|  | 19 | +use core::internal::bounded_int::upcast; | 
| 16 | 20 | use starknet::SyscallResultTrait; | 
| 17 | 21 | 
 | 
| 18 | 22 | /// A handle to the state of a SHA-256 hash. | 
| @@ -81,30 +85,29 @@ pub fn compute_sha256_u32_array( | 
| 81 | 85 | /// 0x7d17648, 0x26381969]); | 
| 82 | 86 | /// ``` | 
| 83 | 87 | pub fn compute_sha256_byte_array(arr: @ByteArray) -> [u32; 8] { | 
|  | 88 | +    let mut iter = arr.span().into_iter(); | 
| 84 | 89 |     let mut word_arr = array![]; | 
| 85 |  | -    let len = arr.len(); | 
| 86 |  | -    let rem = len % 4; | 
| 87 |  | -    let mut index = 0; | 
| 88 |  | -    let rounded_len = len - rem; | 
| 89 |  | -    while index != rounded_len { | 
| 90 |  | -        let word = arr.at(index + 3).unwrap().into() | 
| 91 |  | -            + arr.at(index + 2).unwrap().into() * 0x100 | 
| 92 |  | -            + arr.at(index + 1).unwrap().into() * 0x10000 | 
| 93 |  | -            + arr.at(index).unwrap().into() * 0x1000000; | 
| 94 |  | -        word_arr.append(word); | 
| 95 |  | -        index = index + 4; | 
| 96 |  | -    } | 
| 97 |  | - | 
| 98 |  | -    let last = match rem { | 
| 99 |  | -        0 => 0, | 
| 100 |  | -        1 => arr.at(len - 1).unwrap().into(), | 
| 101 |  | -        2 => arr.at(len - 1).unwrap().into() + arr.at(len - 2).unwrap().into() * 0x100, | 
| 102 |  | -        _ => arr.at(len - 1).unwrap().into() | 
| 103 |  | -            + arr.at(len - 2).unwrap().into() * 0x100 | 
| 104 |  | -            + arr.at(len - 3).unwrap().into() * 0x10000, | 
|  | 90 | + | 
|  | 91 | +    let (last_word, last_word_len) = loop { | 
|  | 92 | +        let Some(b0) = iter.next() else { | 
|  | 93 | +            break (0, 0); | 
|  | 94 | +        }; | 
|  | 95 | +        let Some(b1) = iter.next() else { | 
|  | 96 | +            break (upcast(b0), 1); | 
|  | 97 | +        }; | 
|  | 98 | +        let b0_b1 = conversions::shift_append_byte(b0, b1); | 
|  | 99 | +        let Some(b2) = iter.next() else { | 
|  | 100 | +            break (upcast(b0_b1), 2); | 
|  | 101 | +        }; | 
|  | 102 | +        let b0_b1_b2 = conversions::shift_append_byte(b0_b1, b2); | 
|  | 103 | +        let Some(b3) = iter.next() else { | 
|  | 104 | +            break (upcast(b0_b1_b2), 3); | 
|  | 105 | +        }; | 
|  | 106 | + | 
|  | 107 | +        word_arr.append(upcast(conversions::shift_append_byte(b0_b1_b2, b3))); | 
| 105 | 108 |     }; | 
| 106 | 109 | 
 | 
| 107 |  | -    compute_sha256_u32_array(word_arr, last, rem.into()) | 
|  | 110 | +    compute_sha256_u32_array(word_arr, last_word, last_word_len) | 
| 108 | 111 | } | 
| 109 | 112 | 
 | 
| 110 | 113 | /// Adds padding to the input array according to the SHA-256 specification. | 
| @@ -208,3 +211,41 @@ fn append_zeros(ref arr: Array<u32>, count: felt252) { | 
| 208 | 211 |     } | 
| 209 | 212 |     arr.append(0); | 
| 210 | 213 | } | 
|  | 214 | + | 
|  | 215 | +mod conversions { | 
|  | 216 | +    #[feature("bounded-int-utils")] | 
|  | 217 | +    use core::internal::bounded_int::{self, AddHelper, BoundedInt, MulHelper, UnitInt, upcast}; | 
|  | 218 | + | 
|  | 219 | +    impl U8Shift of MulHelper<u8, UnitInt<0x100>> { | 
|  | 220 | +        type Result = BoundedInt<0, 0xFF00>; | 
|  | 221 | +    } | 
|  | 222 | +    impl U8ShiftAddU8 of AddHelper<U8Shift::Result, u8> { | 
|  | 223 | +        type Result = BoundedInt<0, 0xFFFF>; | 
|  | 224 | +    } | 
|  | 225 | +    impl U16Shift of MulHelper<U8ShiftAddU8::Result, UnitInt<0x100>> { | 
|  | 226 | +        type Result = BoundedInt<0, 0xFFFF00>; | 
|  | 227 | +    } | 
|  | 228 | +    impl U16ShiftAddU8 of AddHelper<U16Shift::Result, u8> { | 
|  | 229 | +        type Result = BoundedInt<0, 0xFFFFFF>; | 
|  | 230 | +    } | 
|  | 231 | +    impl U24Shift of MulHelper<U16ShiftAddU8::Result, UnitInt<0x100>> { | 
|  | 232 | +        type Result = BoundedInt<0, 0xFFFFFF00>; | 
|  | 233 | +    } | 
|  | 234 | +    impl U24ShiftAddU8 of AddHelper<U24Shift::Result, u8> { | 
|  | 235 | +        type Result = BoundedInt<0, 0xFFFFFFFF>; | 
|  | 236 | +    } | 
|  | 237 | +    trait ShiftAppendByte<T> { | 
|  | 238 | +        impl Mul: MulHelper<T, UnitInt<0x100>>; | 
|  | 239 | +        impl Add: AddHelper<Mul::Result, u8>; | 
|  | 240 | +    } | 
|  | 241 | +    impl ShiftAppendByteImpl< | 
|  | 242 | +        T, impl MH: MulHelper<T, UnitInt<0x100>>, impl AH: AddHelper<MH::Result, u8>, | 
|  | 243 | +    > of ShiftAppendByte<T> {} | 
|  | 244 | + | 
|  | 245 | +    /// Shifts a word left by one byte position and appends a new byte. | 
|  | 246 | +    pub fn shift_append_byte<T, impl SAB: ShiftAppendByte<T>>( | 
|  | 247 | +        word: T, byte: u8, | 
|  | 248 | +    ) -> SAB::Add::Result { | 
|  | 249 | +        bounded_int::add::<_, _, SAB::Add>(bounded_int::mul::<_, _, SAB::Mul>(word, 0x100), byte) | 
|  | 250 | +    } | 
|  | 251 | +} | 
0 commit comments