1+ use crate :: hint_processor:: hint_processor_utils:: felt_to_usize;
12use crate :: stdlib:: { borrow:: Cow , collections:: HashMap , prelude:: * } ;
23
34use crate :: types:: errors:: math_errors:: MathError ;
@@ -17,9 +18,11 @@ use crate::{
1718 vm:: { errors:: hint_errors:: HintError , vm_core:: VirtualMachine } ,
1819} ;
1920
21+ use num_bigint:: BigUint ;
22+ use num_integer:: Integer ;
2023use num_traits:: ToPrimitive ;
2124
22- use super :: hint_utils:: get_integer_from_var_name;
25+ use super :: hint_utils:: { get_integer_from_var_name, insert_value_into_ap } ;
2326
2427fn get_fixed_size_u32_array < const T : usize > (
2528 h_range : & Vec < Cow < Felt252 > > ,
@@ -242,6 +245,84 @@ pub fn blake2s_add_uint256_bigend(
242245 Ok ( ( ) )
243246}
244247
248+ /* Implements Hint:
249+ memory[ap] = (ids.end != ids.packed_values) and (memory[ids.packed_values] < 2**63)
250+ */
251+ pub fn is_less_than_63_bits_and_not_end (
252+ vm : & mut VirtualMachine ,
253+ ids_data : & HashMap < String , HintReference > ,
254+ ap_tracking : & ApTracking ,
255+ ) -> Result < ( ) , HintError > {
256+ let end = get_ptr_from_var_name ( "end" , vm, ids_data, ap_tracking) ?;
257+ let packed_values = get_ptr_from_var_name ( "packed_values" , vm, ids_data, ap_tracking) ?;
258+
259+ if end == packed_values {
260+ insert_value_into_ap ( vm, 0 ) ?
261+ } else {
262+ let val = vm. get_integer ( packed_values) ?;
263+ insert_value_into_ap (
264+ vm,
265+ ( val. to_biguint ( ) < ( BigUint :: from ( 1_u32 ) << 63 ) ) as usize ,
266+ ) ?
267+ }
268+ Ok ( ( ) )
269+ }
270+
271+ /* Implements Hint:
272+ offset = 0
273+ for i in range(ids.packed_values_len):
274+ val = (memory[ids.packed_values + i] % PRIME)
275+ val_len = 2 if val < 2**63 else 8
276+ if val_len == 8:
277+ val += 2**255
278+ for i in range(val_len - 1, -1, -1):
279+ val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
280+ assert val == 0
281+ offset += val_len
282+ */
283+ pub fn blake2s_unpack_felts (
284+ vm : & mut VirtualMachine ,
285+ ids_data : & HashMap < String , HintReference > ,
286+ ap_tracking : & ApTracking ,
287+ ) -> Result < ( ) , HintError > {
288+ let packed_values_len =
289+ get_integer_from_var_name ( "packed_values_len" , vm, ids_data, ap_tracking) ?;
290+ let packed_values = get_ptr_from_var_name ( "packed_values" , vm, ids_data, ap_tracking) ?;
291+ let unpacked_u32s = get_ptr_from_var_name ( "unpacked_u32s" , vm, ids_data, ap_tracking) ?;
292+
293+ let vals = vm. get_integer_range ( packed_values, felt_to_usize ( & packed_values_len) ?) ?;
294+ let pow2_32 = BigUint :: from ( 1_u32 ) << 32 ;
295+ let pow2_63 = BigUint :: from ( 1_u32 ) << 63 ;
296+ let pow2_255 = BigUint :: from ( 1_u32 ) << 255 ;
297+
298+ // Split value into either 2 or 8 32-bit limbs.
299+ let out: Vec < MaybeRelocatable > = vals
300+ . into_iter ( )
301+ . map ( |val| val. to_biguint ( ) )
302+ . flat_map ( |val| {
303+ if val < pow2_63 {
304+ let ( high, low) = val. div_rem ( & pow2_32) ;
305+ vec ! [ high, low]
306+ } else {
307+ let mut limbs = vec ! [ BigUint :: from( 0_u32 ) ; 8 ] ;
308+ let mut val: BigUint = val + & pow2_255;
309+ for limb in limbs. iter_mut ( ) . rev ( ) {
310+ let ( q, r) = val. div_rem ( & pow2_32) ;
311+ * limb = r;
312+ val = q;
313+ }
314+ limbs
315+ }
316+ } )
317+ . map ( Felt252 :: from)
318+ . map ( MaybeRelocatable :: from)
319+ . collect ( ) ;
320+
321+ vm. load_data ( unpacked_u32s, & out)
322+ . map_err ( HintError :: Memory ) ?;
323+ Ok ( ( ) )
324+ }
325+
245326/* Implements Hint:
246327 %{
247328 from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress
@@ -604,6 +685,103 @@ mod tests {
604685 . is_none( ) ) ;
605686 }
606687
688+ #[ test]
689+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
690+ fn is_less_than_63_bits_and_not_end_ends ( ) {
691+ let hint_code = hint_code:: IS_LESS_THAN_63_BITS_AND_NOT_END ;
692+ //Create vm
693+ let mut vm = vm ! ( ) ;
694+ //Insert ids into memory
695+ vm. segments = segments ! [ ( ( 1 , 0 ) , ( 1 , 2 ) ) , ( ( 1 , 1 ) , ( 1 , 2 ) ) , ( ( 1 , 2 ) , 123 ) ] ;
696+ vm. set_fp ( 3 ) ;
697+ vm. set_ap ( 3 ) ;
698+ let ids_data = ids_data ! [ "end" , "packed_values" , "value" ] ;
699+ //Execute the hint
700+ assert_matches ! ( run_hint!( vm, ids_data, hint_code) , Ok ( ( ) ) ) ;
701+ //Check data ptr
702+ check_memory ! [ vm. segments. memory, ( ( 1 , 3 ) , 0 ) ] ;
703+ }
704+
705+ #[ test]
706+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
707+ fn is_less_than_63_bits_and_not_end_small ( ) {
708+ let hint_code = hint_code:: IS_LESS_THAN_63_BITS_AND_NOT_END ;
709+ //Create vm
710+ let mut vm = vm ! ( ) ;
711+ //Insert ids into memory
712+ vm. segments = segments ! [ ( ( 1 , 0 ) , ( 1 , 3 ) ) , ( ( 1 , 1 ) , ( 1 , 2 ) ) , ( ( 1 , 2 ) , 123 ) ] ;
713+ vm. set_fp ( 3 ) ;
714+ vm. set_ap ( 3 ) ;
715+ let ids_data = ids_data ! [ "end" , "packed_values" , "value" ] ;
716+ //Execute the hint
717+ assert_matches ! ( run_hint!( vm, ids_data, hint_code) , Ok ( ( ) ) ) ;
718+ //Check data ptr
719+ check_memory ! [ vm. segments. memory, ( ( 1 , 3 ) , 1 ) ] ;
720+ }
721+
722+ #[ test]
723+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
724+ fn is_less_than_63_bits_and_not_end_big ( ) {
725+ let hint_code = hint_code:: IS_LESS_THAN_63_BITS_AND_NOT_END ;
726+ //Create vm
727+ let mut vm = vm ! ( ) ;
728+ //Insert ids into memory
729+ vm. segments = segments ! [
730+ ( ( 1 , 0 ) , ( 1 , 3 ) ) ,
731+ ( ( 1 , 1 ) , ( 1 , 2 ) ) ,
732+ ( ( 1 , 2 ) , 0x10000000000000000 )
733+ ] ;
734+ vm. set_fp ( 3 ) ;
735+ vm. set_ap ( 3 ) ;
736+ let ids_data = ids_data ! [ "end" , "packed_values" , "value" ] ;
737+ //Execute the hint
738+ assert_matches ! ( run_hint!( vm, ids_data, hint_code) , Ok ( ( ) ) ) ;
739+ //Check data ptr
740+ check_memory ! [ vm. segments. memory, ( ( 1 , 3 ) , 0 ) ] ;
741+ }
742+
743+ #[ test]
744+ #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
745+ fn blake2s_unpack_felts ( ) {
746+ let hint_code = hint_code:: BLAKE2S_UNPACK_FELTS ;
747+ //Create vm
748+ let mut vm = vm ! ( ) ;
749+ //Insert ids into memory
750+ vm. segments = segments ! [
751+ ( ( 1 , 0 ) , 2 ) ,
752+ ( ( 1 , 1 ) , ( 1 , 3 ) ) ,
753+ ( ( 1 , 2 ) , ( 2 , 0 ) ) ,
754+ ( ( 1 , 3 ) , 0x123456781234 ) ,
755+ ( ( 1 , 4 ) , 0x1234abcd5678efab1234abcd )
756+ ] ;
757+ vm. set_fp ( 5 ) ;
758+ vm. set_ap ( 5 ) ;
759+ let ids_data = ids_data ! [
760+ "packed_values_len" ,
761+ "packed_values" ,
762+ "unpacked_u32s" ,
763+ "small_value" ,
764+ "big_value"
765+ ] ;
766+ vm. segments . add ( ) ;
767+ //Execute the hint
768+ assert_matches ! ( run_hint!( vm, ids_data, hint_code) , Ok ( ( ) ) ) ;
769+ //Check data ptr
770+ check_memory ! [
771+ vm. segments. memory,
772+ ( ( 2 , 0 ) , 0x1234 ) ,
773+ ( ( 2 , 1 ) , 0x56781234 ) ,
774+ ( ( 2 , 2 ) , 0x80000000 ) ,
775+ ( ( 2 , 3 ) , 0 ) ,
776+ ( ( 2 , 4 ) , 0 ) ,
777+ ( ( 2 , 5 ) , 0 ) ,
778+ ( ( 2 , 6 ) , 0 ) ,
779+ ( ( 2 , 7 ) , 0x1234abcd ) ,
780+ ( ( 2 , 8 ) , 0x5678efab ) ,
781+ ( ( 2 , 9 ) , 0x1234abcd )
782+ ] ;
783+ }
784+
607785 #[ test]
608786 #[ cfg_attr( target_arch = "wasm32" , wasm_bindgen_test) ]
609787 fn blake2s_add_uint256_bigend_valid_non_zero ( ) {
0 commit comments