Skip to content

Commit 43d3fd4

Browse files
committed
Added hints felt unpacking for blake.
1 parent 9690634 commit 43d3fd4

File tree

4 files changed

+197
-1
lines changed

4 files changed

+197
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
* feat: replace `thiserror-no-std` with `thiserror 2` [#1919](https://github.com/lambdaclass/cairo-vm/pull/1919)
88

9+
* feat: Support hints for new blake felt serialization library code [#1994](https://github.com/lambdaclass/cairo-vm/pull/1994)
10+
911
#### [2.0.1] - 2025-03-17
1012

1113
* feat: Limited padding of builtin segments to >=16 [#1981](https://github.com/lambdaclass/cairo-vm/pull/1981)

vm/src/hint_processor/builtin_hint_processor/blake2s_utils.rs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::hint_processor::hint_processor_utils::felt_to_usize;
12
use crate::stdlib::{borrow::Cow, collections::HashMap, prelude::*};
23

34
use crate::types::errors::math_errors::MathError;
@@ -17,6 +18,8 @@ use crate::{
1718
vm::{errors::hint_errors::HintError, vm_core::VirtualMachine},
1819
};
1920

21+
use num_bigint::BigUint;
22+
use num_integer::Integer;
2023
use num_traits::ToPrimitive;
2124

2225
use super::hint_utils::get_integer_from_var_name;
@@ -242,6 +245,83 @@ 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+
let ap = vm.get_ap();
259+
260+
if end == packed_values {
261+
vm.insert_value(ap, 0)?
262+
} else {
263+
let val = vm.get_integer(packed_values)?;
264+
vm.insert_value(
265+
ap,
266+
(val.to_biguint() < (BigUint::from(1_u32) << 63)) as usize,
267+
)?
268+
}
269+
Ok(())
270+
}
271+
272+
/* Implements Hint:
273+
offset = 0
274+
for i in range(ids.packed_values_len):
275+
val = (memory[ids.packed_values + i] % PRIME)
276+
val_len = 2 if val < 2**63 else 8
277+
if val_len == 8:
278+
val += 2**255
279+
for i in range(val_len - 1, -1, -1):
280+
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
281+
assert val == 0
282+
offset += val_len
283+
*/
284+
pub fn blake2s_unpack_felts(
285+
vm: &mut VirtualMachine,
286+
ids_data: &HashMap<String, HintReference>,
287+
ap_tracking: &ApTracking,
288+
) -> Result<(), HintError> {
289+
let packed_values_len =
290+
get_integer_from_var_name("packed_values_len", vm, ids_data, ap_tracking)?;
291+
let packed_values = get_ptr_from_var_name("packed_values", vm, ids_data, ap_tracking)?;
292+
let unpacked_u32s = get_ptr_from_var_name("unpacked_u32s", vm, ids_data, ap_tracking)?;
293+
294+
let vals = vm.get_integer_range(packed_values, felt_to_usize(&packed_values_len)?)?;
295+
let pow2 = |exp: u32| BigUint::from(1_u32) << exp;
296+
297+
// Split value into either 2 or 8 32-bit limbs.
298+
let out: Vec<MaybeRelocatable> = vals
299+
.into_iter()
300+
.map(|val| val.to_biguint())
301+
.flat_map(|val| {
302+
if val < pow2(63) {
303+
let (high, low) = val.div_rem(&(pow2(32)));
304+
vec![high, low]
305+
} else {
306+
let mut limbs = vec![BigUint::from(0_u32); 8];
307+
let mut val: BigUint = val + (pow2(255));
308+
for i in (0..8).rev() {
309+
let (q, r) = val.div_rem(&(pow2(32)));
310+
limbs[i] = r;
311+
val = q;
312+
}
313+
limbs
314+
}
315+
})
316+
.map(Felt252::from)
317+
.map(MaybeRelocatable::from)
318+
.collect();
319+
320+
vm.load_data(unpacked_u32s, &out)
321+
.map_err(HintError::Memory)?;
322+
Ok(())
323+
}
324+
245325
/* Implements Hint:
246326
%{
247327
from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress
@@ -604,6 +684,103 @@ mod tests {
604684
.is_none());
605685
}
606686

687+
#[test]
688+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
689+
fn is_less_than_63_bits_and_not_end_ends() {
690+
let hint_code = hint_code::IS_LESS_THAN_63_BITS_AND_NOT_END;
691+
//Create vm
692+
let mut vm = vm!();
693+
//Insert ids into memory
694+
vm.segments = segments![((1, 0), (1, 2)), ((1, 1), (1, 2)), ((1, 2), 123)];
695+
vm.set_fp(3);
696+
vm.set_ap(3);
697+
let ids_data = ids_data!["end", "packed_values", "value"];
698+
//Execute the hint
699+
assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
700+
//Check data ptr
701+
check_memory![vm.segments.memory, ((1, 3), 0)];
702+
}
703+
704+
#[test]
705+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
706+
fn is_less_than_63_bits_and_not_end_small() {
707+
let hint_code = hint_code::IS_LESS_THAN_63_BITS_AND_NOT_END;
708+
//Create vm
709+
let mut vm = vm!();
710+
//Insert ids into memory
711+
vm.segments = segments![((1, 0), (1, 3)), ((1, 1), (1, 2)), ((1, 2), 123)];
712+
vm.set_fp(3);
713+
vm.set_ap(3);
714+
let ids_data = ids_data!["end", "packed_values", "value"];
715+
//Execute the hint
716+
assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
717+
//Check data ptr
718+
check_memory![vm.segments.memory, ((1, 3), 1)];
719+
}
720+
721+
#[test]
722+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
723+
fn is_less_than_63_bits_and_not_end_big() {
724+
let hint_code = hint_code::IS_LESS_THAN_63_BITS_AND_NOT_END;
725+
//Create vm
726+
let mut vm = vm!();
727+
//Insert ids into memory
728+
vm.segments = segments![
729+
((1, 0), (1, 3)),
730+
((1, 1), (1, 2)),
731+
((1, 2), 0x10000000000000000)
732+
];
733+
vm.set_fp(3);
734+
vm.set_ap(3);
735+
let ids_data = ids_data!["end", "packed_values", "value"];
736+
//Execute the hint
737+
assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
738+
//Check data ptr
739+
check_memory![vm.segments.memory, ((1, 3), 0)];
740+
}
741+
742+
#[test]
743+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
744+
fn blake2s_unpack_felts() {
745+
let hint_code = hint_code::BLAKE2S_UNPACK_FELTS;
746+
//Create vm
747+
let mut vm = vm!();
748+
//Insert ids into memory
749+
vm.segments = segments![
750+
((1, 0), 2),
751+
((1, 1), (1, 3)),
752+
((1, 2), (2, 0)),
753+
((1, 3), 0x123456781234),
754+
((1, 4), 0x1234abcd5678efab1234abcd)
755+
];
756+
vm.set_fp(5);
757+
vm.set_ap(5);
758+
let ids_data = ids_data![
759+
"packed_values_len",
760+
"packed_values",
761+
"unpacked_u32s",
762+
"small_value",
763+
"big_value"
764+
];
765+
vm.segments.add();
766+
//Execute the hint
767+
assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
768+
//Check data ptr
769+
check_memory![
770+
vm.segments.memory,
771+
((2, 0), 0x1234),
772+
((2, 1), 0x56781234),
773+
((2, 2), 0x80000000),
774+
((2, 3), 0),
775+
((2, 4), 0),
776+
((2, 5), 0),
777+
((2, 6), 0),
778+
((2, 7), 0x1234abcd),
779+
((2, 8), 0x5678efab),
780+
((2, 9), 0x1234abcd)
781+
];
782+
}
783+
607784
#[test]
608785
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
609786
fn blake2s_add_uint256_bigend_valid_non_zero() {

vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[cfg(feature = "cairo-0-secp-hints")]
22
use super::secp::cairo0_hints;
33
use super::{
4-
blake2s_utils::finalize_blake2s_v3,
4+
blake2s_utils::{blake2s_unpack_felts, finalize_blake2s_v3, is_more_than_64_bits_and_not_end},
55
ec_recover::{
66
ec_recover_divmod_n_packed, ec_recover_product_div_m, ec_recover_product_mod,
77
ec_recover_sub_a_b,
@@ -360,6 +360,12 @@ impl HintProcessorLogic for BuiltinHintProcessor {
360360
hint_code::BLAKE2S_ADD_UINT256_BIGEND => {
361361
blake2s_add_uint256_bigend(vm, &hint_data.ids_data, &hint_data.ap_tracking)
362362
}
363+
hint_code::IS_LESS_THAN_63_BITS_AND_NOT_END => {
364+
is_more_than_64_bits_and_not_end(vm, &hint_data.ids_data, &hint_data.ap_tracking)
365+
}
366+
hint_code::BLAKE2S_UNPACK_FELTS => {
367+
blake2s_unpack_felts(vm, &hint_data.ids_data, &hint_data.ap_tracking)
368+
}
363369
hint_code::UNSAFE_KECCAK => {
364370
unsafe_keccak(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
365371
}

vm/src/hint_processor/builtin_hint_processor/hint_code.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,17 @@ segments.write_arg(ids.data + 4, [(ids.high >> (B * i)) & MASK for i in range(4)
426426
MASK = 2 ** 32 - 1
427427
segments.write_arg(ids.data, [(ids.high >> (B * (3 - i))) & MASK for i in range(4)])
428428
segments.write_arg(ids.data + 4, [(ids.low >> (B * (3 - i))) & MASK for i in range(4)])"#}),
429+
(IS_LESS_THAN_63_BITS_AND_NOT_END, indoc! {r#"memory[ap] = to_felt_or_relocatable((ids.end != ids.packed_values) and (memory[ids.packed_values] < 2**63))"#}),
430+
(BLAKE2S_UNPACK_FELTS, indoc! {r#"offset = 0
431+
for i in range(ids.packed_values_len):
432+
val = (memory[ids.packed_values + i] % PRIME)
433+
val_len = 2 if val < 2**63 else 8
434+
if val_len == 8:
435+
val += 2**255
436+
for i in range(val_len - 1, -1, -1):
437+
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
438+
assert val == 0
439+
offset += val_len"#}),
429440
(EXAMPLE_BLAKE2S_COMPRESS, indoc! {r#"from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress
430441
431442
_blake2s_input_chunk_size_felts = int(ids.BLAKE2S_INPUT_CHUNK_SIZE_FELTS)

0 commit comments

Comments
 (0)