diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bdf1d8403..be4e67a406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ #### Upcoming Changes +* Implement hint for `starkware.cairo.common.cairo_keccak.keccak._block_permutation` as described by whitelist `starknet/security/whitelists/cairo_keccak.json` [#1046](https://github.com/lambdaclass/cairo-rs/pull/1046) + + `BuiltinHintProcessor` now supports the following hint: + + ```python + %{ + from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func + _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) + assert 0 <= _keccak_state_size_felts < 100 + output_values = keccak_func(memory.get_range( + ids.keccak_ptr_start, _keccak_state_size_felts)) + segments.write_arg(ids.output, output_values) + %} + ``` + * Implement hint for `starkware.cairo.common.cairo_keccak.keccak.finalize_keccak` as described by whitelist `starknet/security/whitelists/cairo_keccak.json` [#1041](https://github.com/lambdaclass/cairo-rs/pull/1041) `BuiltinHintProcessor` now supports the following hint: diff --git a/cairo_programs/_keccak_alternative_hint.cairo b/cairo_programs/_keccak_alternative_hint.cairo index d36504d874..f05b7339ae 100644 --- a/cairo_programs/_keccak_alternative_hint.cairo +++ b/cairo_programs/_keccak_alternative_hint.cairo @@ -12,7 +12,7 @@ from starkware.cairo.common.alloc import alloc from starkware.cairo.common.serialize import serialize_word func _keccak{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( - inputs: felt*, n_bytes: felt, state: felt* + inputs: felt*, n_bytes: felt, state: felt*, use_from_0103: felt, ) -> (output: felt*) { alloc_locals; if (nondet %{ ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES %} != 0) { @@ -23,13 +23,18 @@ func _keccak{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: felt*}( inputs=inputs + KECCAK_FULL_RATE_IN_WORDS, n_bytes=n_bytes - KECCAK_FULL_RATE_IN_BYTES, state=keccak_ptr - KECCAK_STATE_SIZE_FELTS, + use_from_0103=use_from_0103, ); } assert_nn_le(n_bytes, KECCAK_FULL_RATE_IN_BYTES - 1); _prepare_block(inputs=inputs, n_bytes=n_bytes, state=state); - _block_permutation(); + if (use_from_0103 == 1) { + _block_permutation(); + } else { + _block_permutation_whitelist_v2(); + } return (output=keccak_ptr - KECCAK_STATE_SIZE_FELTS); } @@ -49,6 +54,22 @@ func _block_permutation{keccak_ptr: felt*}() { return (); } +func _block_permutation_whitelist_v2{keccak_ptr: felt*}() { + alloc_locals; + let keccak_ptr_start = keccak_ptr; + %{ + from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func + _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) + assert 0 <= _keccak_state_size_felts < 100 + output_values = keccak_func(memory.get_range( + ids.keccak_ptr_start, _keccak_state_size_felts)) + segments.write_arg(ids.output, output_values) + %} + let keccak_ptr = keccak_ptr + KECCAK_STATE_SIZE_FELTS; + + return (); +} + func fill_array(array: felt*, base: felt, array_length: felt, iterator: felt) { if (iterator == array_length) { return (); @@ -76,7 +97,16 @@ func main{output_ptr: felt*, range_check_ptr, bitwise_ptr: BitwiseBuiltin*}() { let n_bytes = 24; let (res: felt*) = _keccak{keccak_ptr=keccak_output}( - inputs=inputs_start, n_bytes=n_bytes, state=state_start + inputs=inputs_start, n_bytes=n_bytes, state=state_start, use_from_0103=1 + ); + + serialize_word(res[0]); + serialize_word(res[1]); + serialize_word(res[2]); + serialize_word(res[4]); + + let (res: felt*) = _keccak{keccak_ptr=keccak_output}( + inputs=inputs_start, n_bytes=n_bytes, state=state_start, use_from_0103=0 ); serialize_word(res[0]); diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 655ee63845..5be6b3f9fa 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -6,9 +6,9 @@ use crate::{ blake2s_add_uint256, blake2s_add_uint256_bigend, compute_blake2s, finalize_blake2s, }, cairo_keccak::keccak_hints::{ - block_permutation, cairo_keccak_finalize_v1, cairo_keccak_finalize_v2, - compare_bytes_in_word_nondet, compare_keccak_full_rate_in_bytes_nondet, - keccak_write_args, + block_permutation_v1, block_permutation_v2, cairo_keccak_finalize_v1, + cairo_keccak_finalize_v2, compare_bytes_in_word_nondet, + compare_keccak_full_rate_in_bytes_nondet, keccak_write_args, }, dict_hint_utils::{ default_dict_new, dict_new, dict_read, dict_squash_copy_dict, @@ -482,8 +482,11 @@ impl HintProcessor for BuiltinHintProcessor { constants, ) } - hint_code::BLOCK_PERMUTATION | hint_code::BLOCK_PERMUTATION_WHITELIST => { - block_permutation(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) + hint_code::BLOCK_PERMUTATION | hint_code::BLOCK_PERMUTATION_WHITELIST_V1 => { + block_permutation_v1(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) + } + hint_code::BLOCK_PERMUTATION_WHITELIST_V2 => { + block_permutation_v2(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) } hint_code::CAIRO_KECCAK_FINALIZE_V1 => { cairo_keccak_finalize_v1(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) diff --git a/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs b/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs index 9cde0c0f31..7b4345c1f1 100644 --- a/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs +++ b/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs @@ -4,6 +4,7 @@ use crate::stdlib::{ prelude::*, }; use crate::{ + felt::Felt252, hint_processor::{ builtin_hint_processor::hint_utils::{ get_integer_from_var_name, get_ptr_from_var_name, insert_value_into_ap, @@ -17,7 +18,6 @@ use crate::{ vm_core::VirtualMachine, }, }; -use felt::Felt252; use num_traits::{ToPrimitive, Zero}; // Constants in package "starkware.cairo.common.cairo_keccak.keccak". @@ -123,7 +123,16 @@ pub fn compare_keccak_full_rate_in_bytes_nondet( } /* -Implements hint: +Implements hints: + %{ + from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func + _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) + assert 0 <= _keccak_state_size_felts < 100 + + output_values = keccak_func(memory.get_range( + ids.keccak_ptr - _keccak_state_size_felts, _keccak_state_size_felts)) + segments.write_arg(ids.keccak_ptr, output_values) + %} %{ from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) @@ -134,7 +143,7 @@ Implements hint: segments.write_arg(ids.keccak_ptr, output_values) %} */ -pub fn block_permutation( +pub(crate) fn block_permutation_v1( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, @@ -143,7 +152,6 @@ pub fn block_permutation( let keccak_state_size_felts = constants .get(KECCAK_STATE_SIZE_FELTS) .ok_or(HintError::MissingConstant(KECCAK_STATE_SIZE_FELTS))?; - if keccak_state_size_felts >= &Felt252::new(100_i32) { return Err(HintError::InvalidKeccakStateSizeFelt252s( keccak_state_size_felts.clone(), @@ -157,7 +165,6 @@ pub fn block_permutation( (keccak_ptr - keccak_state_size_felts)?, keccak_state_size_felts, ); - let mut u64_values = maybe_reloc_vec_to_u64_array(&values)? .try_into() .map_err(|_| VirtualMachineError::SliceToArrayError)?; @@ -174,6 +181,53 @@ pub fn block_permutation( Ok(()) } +/* +Implements hint: + %{ + from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func + _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) + assert 0 <= _keccak_state_size_felts < 100 + output_values = keccak_func(memory.get_range( + ids.keccak_ptr_start, _keccak_state_size_felts)) + segments.write_arg(ids.output, output_values) + %} +*/ +pub(crate) fn block_permutation_v2( + vm: &mut VirtualMachine, + ids_data: &HashMap, + ap_tracking: &ApTracking, + constants: &HashMap, +) -> Result<(), HintError> { + let keccak_state_size_felts = constants + .get(KECCAK_STATE_SIZE_FELTS) + .ok_or(HintError::MissingConstant(KECCAK_STATE_SIZE_FELTS))?; + if keccak_state_size_felts >= &Felt252::from(100_i32) { + return Err(HintError::InvalidKeccakStateSizeFelt252s( + keccak_state_size_felts.clone(), + )); + } + + let keccak_ptr = get_ptr_from_var_name("keccak_ptr_start", vm, ids_data, ap_tracking)?; + + let keccak_state_size_felts = keccak_state_size_felts.to_usize().unwrap(); + let values = vm.get_range(keccak_ptr, keccak_state_size_felts); + let mut u64_values = maybe_reloc_vec_to_u64_array(&values)? + .try_into() + .map_err(|_| VirtualMachineError::SliceToArrayError)?; + + // this function of the keccak crate is the one used instead of keccak_func from + // keccak_utils.py + keccak::f1600(&mut u64_values); + + let bigint_values = u64_array_to_mayberelocatable_vec(&u64_values); + + let output = get_ptr_from_var_name("output", vm, ids_data, ap_tracking)?; + vm.write_arg(output, &bigint_values) + .map_err(HintError::Memory)?; + + Ok(()) +} + fn cairo_keccak_finalize( vm: &mut VirtualMachine, ids_data: &HashMap, diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index cea257e281..e0e6e94a58 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -653,7 +653,7 @@ segments.write_arg(ids.keccak_ptr, output_values)"#; // The 0.10.3 whitelist uses this variant (instead of the one used by the common library), but both hints have the same behaviour // We should check for future refactors that may discard one of the variants -pub const BLOCK_PERMUTATION_WHITELIST: &str = r#"from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func +pub const BLOCK_PERMUTATION_WHITELIST_V1: &str = r#"from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) assert 0 <= _keccak_state_size_felts < 100 @@ -661,6 +661,13 @@ output_values = keccak_func(memory.get_range( ids.keccak_ptr - _keccak_state_size_felts, _keccak_state_size_felts)) segments.write_arg(ids.keccak_ptr, output_values)"#; +pub const BLOCK_PERMUTATION_WHITELIST_V2: &str = r#"from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func +_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) +assert 0 <= _keccak_state_size_felts < 100 +output_values = keccak_func(memory.get_range( + ids.keccak_ptr_start, _keccak_state_size_felts)) +segments.write_arg(ids.output, output_values)"#; + pub const CAIRO_KECCAK_FINALIZE_V1: &str = r#"# Add dummy pairs of input and output. _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) _block_size = int(ids.BLOCK_SIZE)