Skip to content

Commit ea1ca39

Browse files
Add_hint_for_splitting_data_for_blake_with_no_encoding
1 parent 4226352 commit ea1ca39

File tree

3 files changed

+133
-34
lines changed

3 files changed

+133
-34
lines changed

vm/src/hint_processor/builtin_hint_processor/blake2s_utils.rs

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

271-
/* Implements Hint:
271+
pub enum BlakeEncodingMode {
272+
/// 2 limbs if val < 2⁶³, otherwise 8 limbs after adding 2^255.
273+
UseEncoding,
274+
/// Always 8 limbs.
275+
NoEncoding,
276+
}
277+
278+
/* If mode is `BlakeEncodingMode::UseEncoding`, implements the following hint:
272279
offset = 0
273280
for i in range(ids.packed_values_len):
274281
val = (memory[ids.packed_values + i] % PRIME)
275282
val_len = 2 if val < 2**63 else 8
276283
if val_len == 8:
277284
val += 2**255
278-
for i in range(val_len - 1, -1, -1):
285+
for i in range(val_len):
286+
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
287+
assert val == 0
288+
offset += val_len
289+
290+
If mode is `BlakeEncodingMode::NoEncoding`, implements the following hint:
291+
offset = 0
292+
for i in range(ids.packed_values_len):
293+
val = (memory[ids.packed_values + i] % PRIME)
294+
for i in range(8):
279295
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
280296
assert val == 0
281297
offset += val_len
282298
*/
283-
pub fn blake2s_unpack_felts(
299+
pub fn split_packed_felts(
284300
vm: &mut VirtualMachine,
285301
ids_data: &HashMap<String, HintReference>,
286302
ap_tracking: &ApTracking,
303+
mode: BlakeEncodingMode,
287304
) -> Result<(), HintError> {
288305
let packed_values_len =
289306
get_integer_from_var_name("packed_values_len", vm, ids_data, ap_tracking)?;
290307
let packed_values = get_ptr_from_var_name("packed_values", vm, ids_data, ap_tracking)?;
291308
let unpacked_u32s = get_ptr_from_var_name("unpacked_u32s", vm, ids_data, ap_tracking)?;
292309

293310
let vals = vm.get_integer_range(packed_values, felt_to_usize(&packed_values_len)?)?;
311+
294312
let pow2_32 = BigUint::from(1_u32) << 32;
295313
let pow2_63 = BigUint::from(1_u32) << 63;
296314
let pow2_255 = BigUint::from(1_u32) << 255;
297315

298-
// Split value into either 2 or 8 32-bit limbs.
299316
let out: Vec<MaybeRelocatable> = vals
300317
.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 {
318+
.map(|v| v.to_biguint())
319+
.flat_map(|mut val| match mode {
320+
BlakeEncodingMode::NoEncoding => {
321+
// Always 8 little‑endian limbs.
307322
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() {
323+
for limb in &mut limbs {
310324
let (q, r) = val.div_rem(&pow2_32);
311325
*limb = r;
312326
val = q;
313327
}
314328
limbs
315329
}
330+
BlakeEncodingMode::UseEncoding => {
331+
if val < pow2_63 {
332+
// 2 limbs: low, high.
333+
let (high, low) = val.div_rem(&pow2_32);
334+
vec![low, high]
335+
} else {
336+
// 8 limbs after adding 2**255.
337+
val += &pow2_255;
338+
let mut limbs = vec![BigUint::from(0_u32); 8];
339+
for limb in &mut limbs {
340+
let (q, r) = val.div_rem(&pow2_32);
341+
*limb = r;
342+
val = q;
343+
}
344+
limbs
345+
}
346+
}
316347
})
317348
.map(Felt252::from)
318349
.map(MaybeRelocatable::from)
@@ -740,22 +771,28 @@ mod tests {
740771
check_memory![vm.segments.memory, ((1, 3), 0)];
741772
}
742773

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
774+
/// Builds a VM, writes the packed_values_len, packed_values, unpacked_u32s and the
775+
/// actual small and big felts to the memory.
776+
/// Returns the VM and the ids_data HashMap.
777+
fn prepare_vm_for_splitting_felts_for_blake(
778+
small_val: i128,
779+
big_val: i128,
780+
) -> (VirtualMachine, HashMap<String, HintReference>) {
748781
let mut vm = vm!();
749-
//Insert ids into memory
750782
vm.segments = segments![
783+
// ids.packed_values_len = 2
751784
((1, 0), 2),
785+
// ids.packed_values = (1,3)
752786
((1, 1), (1, 3)),
787+
// ids.unpacked_u32s = (2,0)
753788
((1, 2), (2, 0)),
754-
((1, 3), 0x123456781234),
755-
((1, 4), 0x1234abcd5678efab1234abcd)
789+
// packed small / big felts
790+
((1, 3), small_val),
791+
((1, 4), big_val)
756792
];
757793
vm.set_fp(5);
758794
vm.set_ap(5);
795+
759796
let ids_data = ids_data![
760797
"packed_values_len",
761798
"packed_values",
@@ -764,21 +801,64 @@ mod tests {
764801
"big_value"
765802
];
766803
vm.segments.add();
767-
//Execute the hint
768-
assert_matches!(run_hint!(vm, ids_data, hint_code), Ok(()));
769-
//Check data ptr
804+
(vm, ids_data)
805+
}
806+
807+
#[test]
808+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
809+
fn blake2s_encode_and_split_felts() {
810+
let (mut vm, ids_data) = prepare_vm_for_splitting_felts_for_blake(
811+
0x123456781234u128 as i128,
812+
0x1234abcd5678efab1234abcd,
813+
);
814+
assert_matches!(
815+
run_hint!(vm, ids_data, hint_code::BLAKE2S_ENCODE_AND_SPLIT_FELTS),
816+
Ok(())
817+
);
818+
check_memory![
819+
vm.segments.memory,
820+
((2, 0), 0x56781234),
821+
((2, 1), 0x1234),
822+
((2, 2), 0x1234abcd),
823+
((2, 3), 0x5678efab),
824+
((2, 4), 0x1234abcd),
825+
((2, 5), 0),
826+
((2, 6), 0),
827+
((2, 7), 0),
828+
((2, 8), 0),
829+
((2, 9), 0x80000000),
830+
];
831+
}
832+
833+
#[test]
834+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
835+
fn blake2s_split_felts_to_u32s() {
836+
let (mut vm, ids_data) = prepare_vm_for_splitting_felts_for_blake(
837+
0x123456781234u128 as i128,
838+
0x1234abcd5678efab1234abcd5678efab,
839+
);
840+
assert_matches!(
841+
run_hint!(vm, ids_data, hint_code::BLAKE2S_SPLIT_FELTS_TO_U32S),
842+
Ok(())
843+
);
770844
check_memory![
771845
vm.segments.memory,
772-
((2, 0), 0x1234),
773-
((2, 1), 0x56781234),
774-
((2, 2), 0x80000000),
846+
((2, 0), 0x56781234),
847+
((2, 1), 0x1234),
848+
((2, 2), 0),
775849
((2, 3), 0),
776850
((2, 4), 0),
777851
((2, 5), 0),
778852
((2, 6), 0),
779-
((2, 7), 0x1234abcd),
853+
((2, 7), 0),
780854
((2, 8), 0x5678efab),
781-
((2, 9), 0x1234abcd)
855+
((2, 9), 0x1234abcd),
856+
((2, 10), 0x5678efab),
857+
((2, 11), 0x1234abcd),
858+
((2, 12), 0),
859+
((2, 13), 0),
860+
((2, 14), 0),
861+
((2, 15), 0),
782862
];
783863
}
784864

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: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,13 +427,20 @@ 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:
435435
val += 2**255
436-
for i in range(val_len - 1, -1, -1):
436+
for i in range(val_len):
437+
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
438+
assert val == 0
439+
offset += val_len"#}),
440+
(BLAKE2S_SPLIT_FELTS_TO_U32S, indoc! {r#"offset = 0
441+
for i in range(ids.packed_values_len):
442+
val = (memory[ids.packed_values + i] % PRIME)
443+
for i in range(8):
437444
val, memory[ids.unpacked_u32s + offset + i] = divmod(val, 2**32)
438445
assert val == 0
439446
offset += val_len"#}),

0 commit comments

Comments
 (0)