Skip to content

Commit

Permalink
Added tests for fill_holes_in_rc96_segment and `search_sorted_optim…
Browse files Browse the repository at this point in the history
…istic` hints

`search_sorted_optimistic` was previously called `find_element` and was renamed to match the Cairo function it's called from, since there are three variations of very similar hint code.
  • Loading branch information
shamsasari committed Sep 18, 2024
1 parent 322eb04 commit 6574ec9
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 4 deletions.
4 changes: 2 additions & 2 deletions crates/starknet-os/src/hints/find_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::utils::get_variable_from_root_exec_scope;

#[rustfmt::skip]

pub const FIND_ELEMENT: &str = indoc! {r#"array_ptr = ids.array_ptr
pub const SEARCH_SORTED_OPTIMISTIC: &str = indoc! {r#"array_ptr = ids.array_ptr
elm_size = ids.elm_size
assert isinstance(elm_size, int) and elm_size > 0, \
f'Invalid value for elm_size. Got: {elm_size}.'
Expand All @@ -39,7 +39,7 @@ else:
ids.index = n_elms
ids.exists = 0"#};

pub fn find_element(
pub fn search_sorted_optimistic(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
Expand Down
2 changes: 1 addition & 1 deletion crates/starknet-os/src/hints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ fn hints<PCS>() -> HashMap<String, HintImpl> where
hints.insert(execution::WRITE_OLD_BLOCK_TO_STORAGE.into(), execution::write_old_block_to_storage::<PCS>);
hints.insert(execution::WRITE_SYSCALL_RESULT.into(), execution::write_syscall_result::<PCS>);
hints.insert(execution::WRITE_SYSCALL_RESULT_DEPRECATED.into(), execution::write_syscall_result_deprecated::<PCS>);
hints.insert(find_element::FIND_ELEMENT.into(), find_element::find_element);
hints.insert(find_element::SEARCH_SORTED_OPTIMISTIC.into(), find_element::search_sorted_optimistic);
hints.insert(os::CONFIGURE_KZG_MANAGER.into(), os::configure_kzg_manager);
hints.insert(os::WRITE_FULL_OUTPUT_TO_MEM.into(), os::write_full_output_to_mem);
hints.insert(os::SET_AP_TO_NEW_BLOCK_HASH.into(), os::set_ap_to_new_block_hash);
Expand Down
138 changes: 137 additions & 1 deletion crates/starknet-os/src/hints/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ pub mod tests {
use num_bigint::BigInt;
use rstest::{fixture, rstest};
use starknet_api::transaction::Fee;
use vars::ids::{ARRAY_PTR, ELM_SIZE, EXISTS, INDEX, KEY, N_ELMS};

use crate::config::STORED_BLOCK_HASH_BUFFER;
use crate::crypto::pedersen::PedersenHash;
use crate::execution::helper::ContractStorageMap;
use crate::hints::execute_transactions::fill_holes_in_rc96_segment;
use crate::hints::find_element::search_sorted_optimistic;
use crate::hints::*;
use crate::starknet::starknet_storage::OsSingleStarknetStorage;
use crate::storage::dict_storage::DictStorage;
use crate::utils::set_variable_in_root_exec_scope;

#[allow(clippy::upper_case_acronyms)]
type PCS = OsSingleStarknetStorage<DictStorage, PedersenHash>;
Expand Down Expand Up @@ -265,7 +269,7 @@ pub mod tests {
indices
}

// look for any duplicatses in EXTENSIVE_HINTS and print out all occurrences if found
// look for any duplicates in EXTENSIVE_HINTS and print out all occurrences if found
let mut hints: HashMap<String, ExtensiveHintImpl> = HashMap::new();
for (hint, hint_impl) in &EXTENSIVE_HINTS {
let hint_str = hint.to_string();
Expand All @@ -278,4 +282,136 @@ pub mod tests {
);
}
}

#[test]
fn test_fill_holes_in_rc96_segment() {
let mut vm = VirtualMachine::new(false);
vm.set_fp(1);
vm.add_memory_segment();
vm.add_memory_segment();

let mut exec_scopes = ExecutionScopes::new();
let ids_data = ids_data![vars::ids::RANGE_CHECK96_PTR];
let ap_tracking = ApTracking::default();
let constants = HashMap::new();

let mut rc96_segment = vm.add_memory_segment();
rc96_segment.offset = 10;
insert_value_from_var_name(vars::ids::RANGE_CHECK96_PTR, rc96_segment, &mut vm, &ids_data, &ap_tracking)
.expect("insert_value_from_var_name");

let rc96_base = with_offset(rc96_segment, 0);
vm.insert_value(rc96_base, Felt252::THREE).expect("insert value at base");
for i in 1..rc96_segment.offset {
let address = with_offset(rc96_segment, i);
assert_eq!(vm.get_maybe(&address), None);
}

fill_holes_in_rc96_segment(&mut vm, &mut exec_scopes, &ids_data, &ap_tracking, &constants)
.expect("fill_holes_in_rc96_segment failed");

// Make sure existing value isn't overwritten
assert_eq!(vm.get_maybe(&rc96_base), Some(Felt252::THREE.into()));

for i in 1..rc96_segment.offset {
let address = with_offset(rc96_segment, i);
assert_eq!(vm.get_maybe(&address), Some(Felt252::ZERO.into()));
}
}

#[test]
fn test_search_sorted_optimistic_with_zero_sized_elements() {
let mut vm = VirtualMachine::new(false);
vm.add_memory_segment();
vm.add_memory_segment();
vm.set_fp(2);

let mut exec_scopes = ExecutionScopes::new();
let ids_data = ids_data![ARRAY_PTR, ELM_SIZE];
let ap_tracking = ApTracking::default();
let constants = HashMap::new();

let array_ptr = vm.add_memory_segment();
insert_value_from_var_name(ARRAY_PTR, array_ptr, &mut vm, &ids_data, &ap_tracking).unwrap();
insert_value_from_var_name(ELM_SIZE, Felt252::ZERO, &mut vm, &ids_data, &ap_tracking).unwrap();

let result = search_sorted_optimistic(&mut vm, &mut exec_scopes, &ids_data, &ap_tracking, &constants);
assert!(matches!(result, Err(HintError::AssertionFailed(_))), "{:?}", result);
}

#[test]
fn test_search_sorted_optimistic_with_too_many_elements() {
let mut vm = VirtualMachine::new(false);
vm.add_memory_segment();
vm.add_memory_segment();
vm.set_fp(3);

let mut exec_scopes = ExecutionScopes::new();
set_variable_in_root_exec_scope(&mut exec_scopes, vars::scopes::FIND_ELEMENT_MAX_SIZE, Some(2usize));
let ids_data = ids_data![ARRAY_PTR, ELM_SIZE, N_ELMS];
let ap_tracking = ApTracking::default();
let constants = HashMap::new();

let array_ptr = vm.add_memory_segment();
insert_value_from_var_name(ARRAY_PTR, array_ptr, &mut vm, &ids_data, &ap_tracking).unwrap();
insert_value_from_var_name(ELM_SIZE, Felt252::ONE, &mut vm, &ids_data, &ap_tracking).unwrap();
insert_value_from_var_name(N_ELMS, Felt252::THREE, &mut vm, &ids_data, &ap_tracking).unwrap();

let result = search_sorted_optimistic(&mut vm, &mut exec_scopes, &ids_data, &ap_tracking, &constants);
assert!(matches!(result, Err(HintError::AssertionFailed(_))), "{:?}", result);
}

#[test]
fn test_search_sorted_optimistic_present() {
let (index, exists) = exec_search_sorted_optimistic_on_2_4_6_array(Felt252::from(6)).unwrap();
assert_eq!(index, Felt252::TWO);
assert_eq!(exists, Felt252::ONE);
}

#[test]
fn test_search_sorted_optimistic_smaller_value_present() {
let (index, exists) = exec_search_sorted_optimistic_on_2_4_6_array(Felt252::from(3)).unwrap();
assert_eq!(index, Felt252::ONE);
assert_eq!(exists, Felt252::ZERO);
}

#[test]
fn test_search_sorted_optimistic_smaller_value_not_present() {
let (index, exists) = exec_search_sorted_optimistic_on_2_4_6_array(Felt252::ONE).unwrap();
assert_eq!(index, Felt252::ZERO);
assert_eq!(exists, Felt252::ZERO);
}

fn exec_search_sorted_optimistic_on_2_4_6_array(key: Felt252) -> Result<(Felt252, Felt252), HintError> {
let mut vm = VirtualMachine::new(false);
vm.add_memory_segment();
vm.add_memory_segment();
vm.set_fp(6);

let mut exec_scopes = ExecutionScopes::new();
set_variable_in_root_exec_scope(&mut exec_scopes, vars::scopes::FIND_ELEMENT_MAX_SIZE, Some(3usize));
let ids_data = ids_data![ARRAY_PTR, ELM_SIZE, N_ELMS, KEY, INDEX, EXISTS];
let ap_tracking = ApTracking::default();
let constants = HashMap::new();

let array_ptr = vm.add_memory_segment();
vm.insert_value(with_offset(array_ptr, 0), Felt252::from(2))?;
vm.insert_value(with_offset(array_ptr, 1), Felt252::from(4))?;
vm.insert_value(with_offset(array_ptr, 2), Felt252::from(6))?;
insert_value_from_var_name(ARRAY_PTR, array_ptr, &mut vm, &ids_data, &ap_tracking)?;
insert_value_from_var_name(ELM_SIZE, Felt252::ONE, &mut vm, &ids_data, &ap_tracking)?;
insert_value_from_var_name(N_ELMS, Felt252::THREE, &mut vm, &ids_data, &ap_tracking)?;
insert_value_from_var_name(KEY, key, &mut vm, &ids_data, &ap_tracking)?;

search_sorted_optimistic(&mut vm, &mut exec_scopes, &ids_data, &ap_tracking, &constants)?;

let index = get_integer_from_var_name(INDEX, &vm, &ids_data, &ap_tracking)?;
let exists = get_integer_from_var_name(EXISTS, &vm, &ids_data, &ap_tracking)?;
Ok((index, exists))
}

fn with_offset(mut relocatable: Relocatable, offset: usize) -> Relocatable {
relocatable.offset = offset;
relocatable
}
}

0 comments on commit 6574ec9

Please sign in to comment.