Skip to content

Commit 5f734b5

Browse files
optimized sha256_bytearray
1 parent aac178b commit 5f734b5

File tree

1 file changed

+144
-25
lines changed

1 file changed

+144
-25
lines changed

corelib/src/sha256.cairo

Lines changed: 144 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
//! 0x7d17648, 0x26381969]);
1515
//! ```
1616
use starknet::SyscallResultTrait;
17-
17+
use crate::bytes_31::one_shift_left_bytes_u128;
1818
/// A handle to the state of a SHA-256 hash.
1919
pub(crate) extern type Sha256StateHandle;
2020

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

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

0 commit comments

Comments
 (0)