use cairo_vm::Felt252;
use std::collections::HashMap;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{
get_ptr_from_var_name, insert_value_from_var_name,
};
use cairo_vm::hint_processor::hint_processor_definition::HintReference;
use cairo_vm::serde::deserialize_program::ApTracking;
use cairo_vm::types::exec_scope::ExecutionScopes;
use cairo_vm::vm::errors::hint_errors::HintError;
use cairo_vm::vm::vm_core::VirtualMachine;
use starknet_types_core::felt::Felt;
use crate::hints::vars;
pub fn select_builtin(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
let n_selected_builtins: Felt = exec_scopes.get(vars::N_SELECTED_BUILTINS)?;
let select_builtin = if n_selected_builtins == Felt::ZERO {
false
} else {
let selected_encodings =
get_ptr_from_var_name("selected_encodings", vm, ids_data, ap_tracking)?;
let all_encodings = get_ptr_from_var_name("all_encodings", vm, ids_data, ap_tracking)?;
let selected_encoding = vm.get_integer(selected_encodings)?.into_owned();
let builtin_encoding = vm.get_integer(all_encodings)?.into_owned();
selected_encoding == builtin_encoding
};
let select_builtin_felt = Felt252::from(select_builtin);
insert_value_from_var_name(
"select_builtin",
select_builtin_felt,
vm,
ids_data,
ap_tracking,
)?;
if select_builtin {
exec_scopes.insert_value(vars::N_SELECTED_BUILTINS, n_selected_builtins - 1);
}
Ok(())
}
#[cfg(test)]
mod tests {
use crate::test_utils::fill_ids_data_for_test;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::get_integer_from_var_name;
use cairo_vm::types::relocatable::{MaybeRelocatable, Relocatable};
use cairo_vm::Felt252;
use rstest::rstest;
use super::*;
#[rstest]
#[case::should_select_builtin(Felt::ONE, true)]
#[case::should_not_select_builtin(Felt::ZERO, false)]
#[case::no_builtins(Felt::ZERO, true)]
#[case::no_builtins_and_no_match(Felt::ZERO, false)]
fn test_select_builtin(#[case] n_builtins: Felt, #[case] should_select_builtin: bool) {
let mut vm = VirtualMachine::new(false, false);
let builtin_value = 10;
let expected_value = if should_select_builtin {
builtin_value
} else {
builtin_value + 1
};
vm.add_memory_segment();
vm.add_memory_segment();
vm.add_memory_segment();
vm.load_data(
Relocatable::from((1, 0)),
&[
MaybeRelocatable::from((2, 0)),
MaybeRelocatable::from((2, 1)),
],
)
.expect("Failed to load data into memory");
vm.load_data(
Relocatable::from((2, 0)),
&[
MaybeRelocatable::from(Felt252::from(builtin_value)),
MaybeRelocatable::from(Felt252::from(expected_value)),
],
)
.expect("Failed to load data into memory");
vm.set_fp(3);
vm.set_ap(3);
let ids_data =
fill_ids_data_for_test(&["selected_encodings", "all_encodings", "select_builtin"]);
let ap_tracking = ApTracking::new();
let mut exec_scopes = ExecutionScopes::new();
exec_scopes.insert_value(vars::N_SELECTED_BUILTINS, n_builtins);
select_builtin(&mut vm, &mut exec_scopes, &ids_data, &ap_tracking)
.expect("Hint failed unexpectedly");
let select_builtin =
get_integer_from_var_name("select_builtin", &vm, &ids_data, &ap_tracking).unwrap();
let n_selected_builtins: Felt = exec_scopes.get(vars::N_SELECTED_BUILTINS).unwrap();
if (n_builtins != Felt::ZERO) && should_select_builtin {
assert_eq!(select_builtin, Felt252::from(1));
assert_eq!(n_selected_builtins, n_builtins - 1);
} else {
assert_eq!(select_builtin, Felt252::from(0));
assert_eq!(n_selected_builtins, n_builtins);
}
}
}