Skip to content

Commit 2a407bc

Browse files
Add_hint_for_splitting_data_for_blake_with_no_encoding
1 parent 4226352 commit 2a407bc

File tree

3 files changed

+149
-43
lines changed

3 files changed

+149
-43
lines changed

vm/src/hint_processor/builtin_hint_processor/blake2s_utils.rs

Lines changed: 121 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -268,51 +268,89 @@ pub fn is_less_than_63_bits_and_not_end(
268268
Ok(())
269269
}
270270

271-
/* Implements Hint:
271+
/// Represents the encoding mode for Blake2s packed felts splitting.
272+
///
273+
/// - `NoEncoding`: Always splits the value into 8 limbs (u32 words).
274+
/// - `UseEncoding`: Uses 2 limbs if the value is less than 2^63, otherwise splits
275+
/// into 8 limbs after adding 2^255.
276+
///
277+
/// This is used to control how packed felts are unpacked into u32 limbs for Blake2s hashing.
278+
pub enum BlakeEncodingMode {
279+
NoEncoding,
280+
UseEncoding,
281+
}
282+
283+
/* If mode is `BlakeEncodingMode::UseEncoding`, implements the following hint:
272284
offset = 0
273285
for i in range(ids.packed_values_len):
274286
val = (memory[ids.packed_values + i] % PRIME)
275287
val_len = 2 if val < 2**63 else 8
276288
if val_len == 8:
277-
val += 2**255
278-
for i in range(val_len - 1, -1, -1):
289+
# Treat `val` as a u256 and set its most significant bit (bit 255).
290+
val += 1 << 255
291+
for i in range(val_len):
292+
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
293+
assert val == 0
294+
offset += val_len
295+
296+
If mode is `BlakeEncodingMode::NoEncoding`, implements the following hint:
297+
offset = 0
298+
for i in range(ids.packed_values_len):
299+
val = (memory[ids.packed_values + i] % PRIME)
300+
val_len = 8
301+
for i in range(val_len):
279302
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
280303
assert val == 0
281304
offset += val_len
282305
*/
283-
pub fn blake2s_unpack_felts(
306+
pub fn split_packed_felts(
284307
vm: &mut VirtualMachine,
285308
ids_data: &HashMap<String, HintReference>,
286309
ap_tracking: &ApTracking,
310+
mode: BlakeEncodingMode,
287311
) -> Result<(), HintError> {
288312
let packed_values_len =
289313
get_integer_from_var_name("packed_values_len", vm, ids_data, ap_tracking)?;
290314
let packed_values = get_ptr_from_var_name("packed_values", vm, ids_data, ap_tracking)?;
291315
let unpacked_u32s = get_ptr_from_var_name("unpacked_u32s", vm, ids_data, ap_tracking)?;
292316

293317
let vals = vm.get_integer_range(packed_values, felt_to_usize(&packed_values_len)?)?;
318+
294319
let pow2_32 = BigUint::from(1_u32) << 32;
295320
let pow2_63 = BigUint::from(1_u32) << 63;
296321
let pow2_255 = BigUint::from(1_u32) << 255;
297322

298-
// Split value into either 2 or 8 32-bit limbs.
323+
// Split the value into 8 limbs, each of which is a u32.
324+
let split_fixed8 = |mut val: BigUint| -> Vec<BigUint> {
325+
let mut limbs = vec![BigUint::from(0_u32); 8];
326+
for limb in &mut limbs {
327+
let (q, r) = val.div_rem(&pow2_32);
328+
*limb = r;
329+
val = q;
330+
}
331+
limbs
332+
};
333+
334+
// Split the value into 2 limbs if it is less than 2^63, or 8 limbs after adding 2^255.
335+
let split_encoded = |mut val: BigUint| -> Vec<BigUint> {
336+
if val < pow2_63 {
337+
// Two‑limb representation.
338+
let (high, low) = val.div_rem(&pow2_32);
339+
vec![low, high]
340+
} else {
341+
// Eight limbs after adding 2^255.
342+
val += &pow2_255;
343+
split_fixed8(val)
344+
}
345+
};
346+
347+
// Unpack the values into u32 limbs in little-endian order according to the specified mode.
299348
let out: Vec<MaybeRelocatable> = vals
300349
.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-
}
350+
.map(|v| v.to_biguint())
351+
.flat_map(|val| match mode {
352+
BlakeEncodingMode::NoEncoding => split_fixed8(val),
353+
BlakeEncodingMode::UseEncoding => split_encoded(val),
316354
})
317355
.map(Felt252::from)
318356
.map(MaybeRelocatable::from)
@@ -740,22 +778,28 @@ mod tests {
740778
check_memory![vm.segments.memory, ((1, 3), 0)];
741779
}
742780

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
781+
/// Builds a VM, writes the packed_values_len, packed_values, unpacked_u32s and the
782+
/// actual small and big felts to the memory.
783+
/// Returns the VM and the ids_data HashMap.
784+
fn prepare_vm_for_splitting_felts_for_blake(
785+
small_val: i128,
786+
big_val: i128,
787+
) -> (VirtualMachine, HashMap<String, HintReference>) {
748788
let mut vm = vm!();
749-
//Insert ids into memory
750789
vm.segments = segments![
790+
// ids.packed_values_len = 2
751791
((1, 0), 2),
792+
// ids.packed_values = (1,3)
752793
((1, 1), (1, 3)),
794+
// ids.unpacked_u32s = (2,0)
753795
((1, 2), (2, 0)),
754-
((1, 3), 0x123456781234),
755-
((1, 4), 0x1234abcd5678efab1234abcd)
796+
// packed small / big felts
797+
((1, 3), small_val),
798+
((1, 4), big_val)
756799
];
757800
vm.set_fp(5);
758801
vm.set_ap(5);
802+
759803
let ids_data = ids_data![
760804
"packed_values_len",
761805
"packed_values",
@@ -764,21 +808,62 @@ mod tests {
764808
"big_value"
765809
];
766810
vm.segments.add();
767-
//Execute the hint
768-
assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
769-
//Check data ptr
811+
(vm, ids_data)
812+
}
813+
814+
#[test]
815+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
816+
fn blake2s_encode_and_split_felts() {
817+
let (mut vm, ids_data) =
818+
prepare_vm_for_splitting_felts_for_blake(0x123456781234, 0x1234abcd5678efab1234abcd);
819+
assert_matches!(
820+
run_hint!(vm, ids_data, hint_code::BLAKE2S_ENCODE_AND_SPLIT_FELTS),
821+
Ok(())
822+
);
770823
check_memory![
771824
vm.segments.memory,
772-
((2, 0), 0x1234),
773-
((2, 1), 0x56781234),
774-
((2, 2), 0x80000000),
825+
((2, 0), 0x56781234),
826+
((2, 1), 0x1234),
827+
((2, 2), 0x1234abcd),
828+
((2, 3), 0x5678efab),
829+
((2, 4), 0x1234abcd),
830+
((2, 5), 0),
831+
((2, 6), 0),
832+
((2, 7), 0),
833+
((2, 8), 0),
834+
((2, 9), 0x80000000),
835+
];
836+
}
837+
838+
#[test]
839+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
840+
fn blake2s_split_felts_to_u32s() {
841+
let (mut vm, ids_data) = prepare_vm_for_splitting_felts_for_blake(
842+
0x123456781234,
843+
0x1234abcd5678efab1234abcd5678efab,
844+
);
845+
assert_matches!(
846+
run_hint!(vm, ids_data, hint_code::BLAKE2S_SPLIT_FELTS_TO_U32S),
847+
Ok(())
848+
);
849+
check_memory![
850+
vm.segments.memory,
851+
((2, 0), 0x56781234),
852+
((2, 1), 0x1234),
853+
((2, 2), 0),
775854
((2, 3), 0),
776855
((2, 4), 0),
777856
((2, 5), 0),
778857
((2, 6), 0),
779-
((2, 7), 0x1234abcd),
858+
((2, 7), 0),
780859
((2, 8), 0x5678efab),
781-
((2, 9), 0x1234abcd)
860+
((2, 9), 0x1234abcd),
861+
((2, 10), 0x5678efab),
862+
((2, 11), 0x1234abcd),
863+
((2, 12), 0),
864+
((2, 13), 0),
865+
((2, 14), 0),
866+
((2, 15), 0),
782867
];
783868
}
784869

vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use super::blake2s_utils::example_blake2s_compress;
22
use super::{
3-
blake2s_utils::{blake2s_unpack_felts, finalize_blake2s_v3, is_less_than_63_bits_and_not_end},
3+
blake2s_utils::{
4+
finalize_blake2s_v3, is_less_than_63_bits_and_not_end, split_packed_felts,
5+
BlakeEncodingMode,
6+
},
47
ec_recover::{
58
ec_recover_divmod_n_packed, ec_recover_product_div_m, ec_recover_product_mod,
69
ec_recover_sub_a_b,
@@ -363,9 +366,18 @@ impl HintProcessorLogic for BuiltinHintProcessor {
363366
hint_code::IS_LESS_THAN_63_BITS_AND_NOT_END => {
364367
is_less_than_63_bits_and_not_end(vm, &hint_data.ids_data, &hint_data.ap_tracking)
365368
}
366-
hint_code::BLAKE2S_UNPACK_FELTS => {
367-
blake2s_unpack_felts(vm, &hint_data.ids_data, &hint_data.ap_tracking)
368-
}
369+
hint_code::BLAKE2S_ENCODE_AND_SPLIT_FELTS => split_packed_felts(
370+
vm,
371+
&hint_data.ids_data,
372+
&hint_data.ap_tracking,
373+
BlakeEncodingMode::UseEncoding,
374+
),
375+
hint_code::BLAKE2S_SPLIT_FELTS_TO_U32S => split_packed_felts(
376+
vm,
377+
&hint_data.ids_data,
378+
&hint_data.ap_tracking,
379+
BlakeEncodingMode::NoEncoding,
380+
),
369381
hint_code::UNSAFE_KECCAK => {
370382
unsafe_keccak(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking)
371383
}

vm/src/hint_processor/builtin_hint_processor/hint_code.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,22 @@ 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)])"#}),
429429
(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
430+
(BLAKE2S_ENCODE_AND_SPLIT_FELTS, indoc! {r#"offset = 0
431431
for i in range(ids.packed_values_len):
432432
val = (memory[ids.packed_values + i] % PRIME)
433433
val_len = 2 if val < 2**63 else 8
434434
if val_len == 8:
435-
val += 2**255
436-
for i in range(val_len - 1, -1, -1):
435+
# Treat `val` as a u256 and set its most significant bit (bit 255).
436+
val += 1 << 255
437+
for i in range(val_len):
438+
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
439+
assert val == 0
440+
offset += val_len"#}),
441+
(BLAKE2S_SPLIT_FELTS_TO_U32S, indoc! {r#"offset = 0
442+
for i in range(ids.packed_values_len):
443+
val = (memory[ids.packed_values + i] % PRIME)
444+
val_len = 8
445+
for i in range(val_len):
437446
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
438447
assert val == 0
439448
offset += val_len"#}),

0 commit comments

Comments
 (0)