Skip to content

Commit e34c042

Browse files
optimized sha256_bytearray
1 parent aac178b commit e34c042

File tree

1 file changed

+136
-23
lines changed

1 file changed

+136
-23
lines changed

corelib/src/sha256.cairo

Lines changed: 136 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
//! 0x7d17648, 0x26381969]);
1515
//! ```
1616
use starknet::SyscallResultTrait;
17-
17+
use crate::bytes_31::{
18+
one_shift_left_bytes_u128,
19+
};
1820
/// A handle to the state of a SHA-256 hash.
1921
pub(crate) extern type Sha256StateHandle;
2022

@@ -81,30 +83,50 @@ pub fn compute_sha256_u32_array(
8183
//! 0x7d17648, 0x26381969]);
8284
/// ```
8385
pub fn compute_sha256_byte_array(arr: @ByteArray) -> [u32; 8] {
84-
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,
86+
let mut span = Span { snapshot: arr.data };
87+
88+
let mut words_arr = array![];
89+
let mut last_word = 0;
90+
let mut last_word_len = 0;
91+
while let Option::Some(byte_31) = span.pop_front() {
92+
let u256 { mut low, mut high } = (*byte_31).into();
93+
let mut shift = BYTES_IN_U128 - 1 - 4 + last_word_len;
94+
append_u128_to_words_array(ref words_arr, high, ref last_word, ref last_word_len, shift);
95+
let mut shift = BYTES_IN_U128 - 4 + last_word_len;
96+
append_u128_to_words_array(ref words_arr, low, ref last_word, ref last_word_len, shift);
10597
};
98+
let u256 { mut low, mut high } = (*arr.pending_word).into();
99+
if *arr.pending_word_len > BYTES_IN_U128 {
100+
let mut shift = *arr.pending_word_len - BYTES_IN_U128 + last_word_len;
101+
if shift >= 4 {
102+
shift = shift - 4;
103+
append_u128_to_words_array_partial(
104+
ref words_arr, high, ref last_word, ref last_word_len, shift
105+
);
106+
} else {
107+
last_word = (last_word.into() * one_shift_left_bytes_u128(last_word_len) + high)
108+
.try_into()
109+
.unwrap();
110+
last_word_len = last_word_len + *arr.pending_word_len - BYTES_IN_U128;
111+
}
112+
let mut shift = BYTES_IN_U128 - 4 + last_word_len;
113+
append_u128_to_words_array(ref words_arr, low, ref last_word, ref last_word_len, shift);
114+
} else {
115+
let mut shift = *arr.pending_word_len + last_word_len;
116+
if shift >= 4 {
117+
shift = shift - 4;
118+
append_u128_to_words_array_partial(
119+
ref words_arr, low, ref last_word, ref last_word_len, shift
120+
);
121+
} else {
122+
last_word = (last_word.into() * one_shift_left_bytes_u128(*arr.pending_word_len) + low)
123+
.try_into()
124+
.unwrap();
125+
last_word_len = last_word_len + *arr.pending_word_len;
126+
}
127+
}
106128

107-
compute_sha256_u32_array(word_arr, last, rem.into())
129+
return compute_sha256_u32_array(words_arr, last_word, last_word_len);
108130
}
109131

110132
/// Adds padding to the input array according to the SHA-256 specification.
@@ -208,3 +230,94 @@ fn append_zeros(ref arr: Array<u32>, count: felt252) {
208230
}
209231
arr.append(0);
210232
}
233+
234+
const BYTES_IN_U128: usize = 16;
235+
236+
/// Appends `val` to the words array.
237+
fn append_u128_to_words_array_partial(
238+
ref words_arr: Array<u32>, val: u128, ref last_word: u32, ref last_word_len: u32, mut shift: u32
239+
) {
240+
words_arr
241+
.append(
242+
(last_word.into() * one_shift_left_bytes_u128(4 - last_word_len)
243+
+ val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
244+
.try_into()
245+
.unwrap()
246+
);
247+
if shift < 4 {
248+
last_word = (val % one_shift_left_bytes_u128(shift)).try_into().unwrap();
249+
last_word_len = shift;
250+
return;
251+
}
252+
shift = shift - 4;
253+
words_arr
254+
.append(
255+
(val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
256+
.try_into()
257+
.unwrap()
258+
);
259+
if shift < 4 {
260+
last_word = (val % one_shift_left_bytes_u128(shift)).try_into().unwrap();
261+
last_word_len = shift;
262+
return;
263+
}
264+
shift = shift - 4;
265+
words_arr
266+
.append(
267+
(val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
268+
.try_into()
269+
.unwrap()
270+
);
271+
if shift < 4 {
272+
last_word = (val % one_shift_left_bytes_u128(shift)).try_into().unwrap();
273+
last_word_len = shift;
274+
return;
275+
}
276+
shift = shift - 4;
277+
words_arr
278+
.append(
279+
(val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
280+
.try_into()
281+
.unwrap()
282+
);
283+
last_word = (val % one_shift_left_bytes_u128(shift)).try_into().unwrap();
284+
last_word_len = shift;
285+
}
286+
287+
/// Appends `val` to the words array.
288+
fn append_u128_to_words_array(
289+
ref words_arr: Array<u32>, val: u128, ref last_word: u32, ref last_word_len: u32, mut shift: u32
290+
) {
291+
words_arr
292+
.append(
293+
(last_word.into() * one_shift_left_bytes_u128(4 - last_word_len)
294+
+ val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
295+
.try_into()
296+
.unwrap()
297+
);
298+
shift = shift - 4;
299+
words_arr
300+
.append(
301+
(val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
302+
.try_into()
303+
.unwrap()
304+
);
305+
shift = shift - 4;
306+
words_arr
307+
.append(
308+
(val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
309+
.try_into()
310+
.unwrap()
311+
);
312+
if shift != 3 {
313+
shift = shift - 4;
314+
words_arr
315+
.append(
316+
(val / one_shift_left_bytes_u128(shift) % one_shift_left_bytes_u128(4))
317+
.try_into()
318+
.unwrap()
319+
);
320+
}
321+
last_word = (val % one_shift_left_bytes_u128(shift)).try_into().unwrap();
322+
last_word_len = shift;
323+
}

0 commit comments

Comments
 (0)