Skip to content

Commit

Permalink
feat(hint): support hint #66 for keccak_finalize
Browse files Browse the repository at this point in the history
Version from whitelist `starknet/security/whitelists/cairo_keccak.json`,
differs from the current one in bounds for `_block_size`, `1000` instead
of `10`.
  • Loading branch information
Oppen committed Apr 24, 2023
1 parent fb73125 commit 83e7f87
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 21 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@

#### Upcoming Changes

* 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:

```python
%{
# Add dummy pairs of input and output.
_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)
_block_size = int(ids.BLOCK_SIZE)
assert 0 <= _keccak_state_size_felts < 100
assert 0 <= _block_size < 1000
inp = [0] * _keccak_state_size_felts
padding = (inp + keccak_func(inp)) * _block_size
segments.write_arg(ids.keccak_ptr_end, padding)
%}
```

* Implement hint on ec_recover.json whitelist [#1036](https://github.com/lambdaclass/cairo-rs/pull/1036):

`BuiltinHintProcessor` now supports the following hint:
Expand Down
60 changes: 60 additions & 0 deletions cairo_programs/cairo_finalize_keccak_block_size_1000.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
%builtins range_check bitwise

from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
from starkware.cairo.common.cairo_keccak.keccak import _finalize_keccak_inner, cairo_keccak, BLOCK_SIZE, KECCAK_STATE_SIZE_FELTS
from starkware.cairo.common.math import unsigned_div_rem
from starkware.cairo.common.uint256 import Uint256

// Verifies that the results of cairo_keccak() are valid. For optimization, this can be called only
// once after all the keccak calculations are completed.
// Version copied from starknet/security/whitelists/cairo_keccak.json
func finalize_keccak{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(
keccak_ptr_start: felt*, keccak_ptr_end: felt*
) {
alloc_locals;

tempvar n = (keccak_ptr_end - keccak_ptr_start) / (2 * KECCAK_STATE_SIZE_FELTS);
if (n == 0) {
return ();
}

%{
# Add dummy pairs of input and output.
_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)
_block_size = int(ids.BLOCK_SIZE)
assert 0 <= _keccak_state_size_felts < 100
assert 0 <= _block_size < 1000
inp = [0] * _keccak_state_size_felts
padding = (inp + keccak_func(inp)) * _block_size
segments.write_arg(ids.keccak_ptr_end, padding)
%}

// Compute the amount of blocks (rounded up).
let (local q, r) = unsigned_div_rem(n + BLOCK_SIZE - 1, BLOCK_SIZE);
_finalize_keccak_inner(keccak_ptr_start, n=q);
return ();
}

func main{range_check_ptr: felt, bitwise_ptr: BitwiseBuiltin*}() {
alloc_locals;

let (keccak_ptr: felt*) = alloc();
let keccak_ptr_start = keccak_ptr;

let (inputs: felt*) = alloc();

assert inputs[0] = 8031924123371070792;
assert inputs[1] = 560229490;

let n_bytes = 16;

let (res: Uint256) = cairo_keccak{keccak_ptr=keccak_ptr}(inputs=inputs, n_bytes=n_bytes);

assert res.low = 293431514620200399776069983710520819074;
assert res.high = 317109767021952548743448767588473366791;

finalize_keccak(keccak_ptr_start=keccak_ptr_start, keccak_ptr_end=keccak_ptr);

return ();
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use crate::{
blake2s_add_uint256, blake2s_add_uint256_bigend, compute_blake2s, finalize_blake2s,
},
cairo_keccak::keccak_hints::{
block_permutation, cairo_keccak_finalize, compare_bytes_in_word_nondet,
compare_keccak_full_rate_in_bytes_nondet, keccak_write_args,
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,
},
dict_hint_utils::{
default_dict_new, dict_new, dict_read, dict_squash_copy_dict,
Expand Down Expand Up @@ -484,8 +485,11 @@ impl HintProcessor for BuiltinHintProcessor {
hint_code::BLOCK_PERMUTATION | hint_code::BLOCK_PERMUTATION_WHITELIST => {
block_permutation(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants)
}
hint_code::CAIRO_KECCAK_FINALIZE => {
cairo_keccak_finalize(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)
}
hint_code::CAIRO_KECCAK_FINALIZE_V2 => {
cairo_keccak_finalize_v2(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants)
}
hint_code::FAST_EC_ADD_ASSIGN_NEW_X => fast_ec_add_assign_new_x(
vm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,23 +174,12 @@ pub fn block_permutation(
Ok(())
}

/* Implements hint:
%{
# Add dummy pairs of input and output.
_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)
_block_size = int(ids.BLOCK_SIZE)
assert 0 <= _keccak_state_size_felts < 100
assert 0 <= _block_size < 10
inp = [0] * _keccak_state_size_felts
padding = (inp + keccak_func(inp)) * _block_size
segments.write_arg(ids.keccak_ptr_end, padding)
%}
*/
pub fn cairo_keccak_finalize(
fn cairo_keccak_finalize(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
constants: &HashMap<String, Felt252>,
block_size_limit: usize,
) -> Result<(), HintError> {
let keccak_state_size_felts = constants
.get(KECCAK_STATE_SIZE_FELTS)
Expand All @@ -205,9 +194,9 @@ pub fn cairo_keccak_finalize(
));
}

if block_size >= &Felt252::new(10_i32) {
if block_size >= &Felt252::new(block_size_limit) {
return Err(HintError::InvalidBlockSize(block_size.clone()));
}
};

let keccak_state_size_felts = keccak_state_size_felts.to_usize().unwrap();
let block_size = block_size.to_usize().unwrap();
Expand All @@ -234,6 +223,48 @@ pub fn cairo_keccak_finalize(
Ok(())
}

/* Implements hint:
%{
# Add dummy pairs of input and output.
_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)
_block_size = int(ids.BLOCK_SIZE)
assert 0 <= _keccak_state_size_felts < 100
assert 0 <= _block_size < 10
inp = [0] * _keccak_state_size_felts
padding = (inp + keccak_func(inp)) * _block_size
segments.write_arg(ids.keccak_ptr_end, padding)
%}
*/
pub(crate) fn cairo_keccak_finalize_v1(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
cairo_keccak_finalize(vm, ids_data, ap_tracking, constants, 10)
}

/* Implements hint:
%{
# Add dummy pairs of input and output.
_keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS)
_block_size = int(ids.BLOCK_SIZE)
assert 0 <= _keccak_state_size_felts < 100
assert 0 <= _block_size < 1000
inp = [0] * _keccak_state_size_felts
padding = (inp + keccak_func(inp)) * _block_size
segments.write_arg(ids.keccak_ptr_end, padding)
%}
*/
pub(crate) fn cairo_keccak_finalize_v2(
vm: &mut VirtualMachine,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
cairo_keccak_finalize(vm, ids_data, ap_tracking, constants, 1000)
}

// Helper function to transform a vector of MaybeRelocatables into a vector
// of u64. Raises error if there are None's or if MaybeRelocatables are not Bigints.
pub(crate) fn maybe_reloc_vec_to_u64_array(
Expand Down
11 changes: 10 additions & 1 deletion src/hint_processor/builtin_hint_processor/hint_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ 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 CAIRO_KECCAK_FINALIZE: &str = r#"# Add dummy pairs of input and output.
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)
assert 0 <= _keccak_state_size_felts < 100
Expand All @@ -670,6 +670,15 @@ inp = [0] * _keccak_state_size_felts
padding = (inp + keccak_func(inp)) * _block_size
segments.write_arg(ids.keccak_ptr_end, padding)"#;

pub const CAIRO_KECCAK_FINALIZE_V2: &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)
assert 0 <= _keccak_state_size_felts < 100
assert 0 <= _block_size < 1000
inp = [0] * _keccak_state_size_felts
padding = (inp + keccak_func(inp)) * _block_size
segments.write_arg(ids.keccak_ptr_end, padding)"#;

pub const FAST_EC_ADD_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack
slope = pack(ids.slope, PRIME)
Expand Down
10 changes: 9 additions & 1 deletion src/tests/cairo_run_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -458,11 +458,19 @@ fn keccak_copy_inputs() {

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_finalize_keccak() {
fn cairo_finalize_keccak_v1() {
let program_data = include_bytes!("../../cairo_programs/cairo_finalize_keccak.json");
run_program_simple_with_memory_holes(program_data.as_slice(), 50);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn cairo_finalize_keccak_v2() {
let program_data =
include_bytes!("../../cairo_programs/cairo_finalize_keccak_block_size_1000.json");
run_program_simple_with_memory_holes(program_data.as_slice(), 50);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn operations_with_data_structures() {
Expand Down

0 comments on commit 83e7f87

Please sign in to comment.