Skip to content

Commit

Permalink
Feature: GET_STATE_ENTRY_AND_SET_NEW_STATE_ENTRY hints (#98)
Browse files Browse the repository at this point in the history
  • Loading branch information
odesenfans authored Mar 27, 2024
1 parent cc3c3d7 commit f41c64e
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 51 deletions.
121 changes: 106 additions & 15 deletions src/hints/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{
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::types::relocatable::MaybeRelocatable;
use cairo_vm::types::relocatable::{MaybeRelocatable, Relocatable};
use cairo_vm::vm::errors::hint_errors::HintError;
use cairo_vm::vm::vm_core::VirtualMachine;
use cairo_vm::Felt252;
Expand Down Expand Up @@ -174,33 +174,124 @@ pub fn enter_scope_syscall_handler(
Ok(())
}

pub const GET_STATE_ENTRY: &str = indoc! {r##"
# Fetch a state_entry in this hint and validate it in the update at the end
# of this function.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[ids.contract_address]"##
};
pub fn get_state_entry(
fn get_state_entry(
dict_ptr: Relocatable,
key: Felt252,
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let key = get_integer_from_var_name("contract_address", vm, ids_data, ap_tracking)?;
let dict_ptr = get_ptr_from_var_name("contract_state_changes", vm, ids_data, ap_tracking)?;
let val = match exec_scopes.get_dict_manager()?.borrow().get_tracker(dict_ptr)?.data.clone() {
Dictionary::SimpleDictionary(dict) => dict
.get(&MaybeRelocatable::Int(key.into_owned()))
.expect("State changes dictionnary shouldn't be None")
.clone(),
Dictionary::SimpleDictionary(dict) => dict.get(&MaybeRelocatable::Int(key)).cloned(),
Dictionary::DefaultDictionary { dict: _d, default_value: _v } => {
panic!("State changes dict shouldn't be a default dict")
return Err(HintError::CustomHint(
"State changes dictionary should not be a default dict".to_string().into_boxed_str(),
));
}
};
let val =
val.ok_or(HintError::CustomHint("State changes dictionnary should not be None".to_string().into_boxed_str()))?;

insert_value_from_var_name("state_entry", val, vm, ids_data, ap_tracking)?;
Ok(())
}

pub const GET_CONTRACT_ADDRESS_STATE_ENTRY: &str = indoc! {r##"
# Fetch a state_entry in this hint and validate it in the update at the end
# of this function.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[ids.contract_address]"##
};

pub const GET_CONTRACT_ADDRESS_STATE_ENTRY_2: &str = indoc! {r#"
# Fetch a state_entry in this hint and validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
ids.contract_address
]"#
};

pub fn get_contract_address_state_entry(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let dict_ptr = get_ptr_from_var_name(vars::ids::CONTRACT_STATE_CHANGES, vm, ids_data, ap_tracking)?;
let key = get_integer_from_var_name(vars::ids::CONTRACT_ADDRESS, vm, ids_data, ap_tracking)?;

get_state_entry(dict_ptr, key.into_owned(), vm, exec_scopes, ids_data, ap_tracking)?;

Ok(())
}
fn get_state_entry_and_set_new_state_entry(
dict_ptr: Relocatable,
key: Felt252,
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
) -> Result<(), HintError> {
get_state_entry(dict_ptr, key, vm, exec_scopes, ids_data, ap_tracking)?;

let new_segment = vm.add_memory_segment();
insert_value_from_var_name(vars::ids::NEW_STATE_ENTRY, new_segment, vm, ids_data, ap_tracking)?;

Ok(())
}

pub const GET_BLOCK_HASH_CONTRACT_ADDRESS_STATE_ENTRY_AND_SET_NEW_STATE_ENTRY: &str = indoc! {r#"
# Fetch a state_entry in this hint. Validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
ids.BLOCK_HASH_CONTRACT_ADDRESS]
ids.new_state_entry = segments.add()"#
};

pub fn get_block_hash_contract_address_state_entry_and_set_new_state_entry(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let dict_ptr = get_ptr_from_var_name(vars::ids::CONTRACT_STATE_CHANGES, vm, ids_data, ap_tracking)?;
let key = get_integer_from_var_name(vars::ids::BLOCK_HASH_CONTRACT_ADDRESS, vm, ids_data, ap_tracking)?;

get_state_entry_and_set_new_state_entry(dict_ptr, key.into_owned(), vm, exec_scopes, ids_data, ap_tracking)?;

Ok(())
}

pub const GET_CONTRACT_ADDRESS_STATE_ENTRY_AND_SET_NEW_STATE_ENTRY: &str = indoc! {r#"
# Fetch a state_entry in this hint and validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[ids.contract_address]
ids.new_state_entry = segments.add()"#
};

pub const GET_CONTRACT_ADDRESS_STATE_ENTRY_AND_SET_NEW_STATE_ENTRY_2: &str = indoc! {r#"
# Fetch a state_entry in this hint and validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
ids.contract_address
]
ids.new_state_entry = segments.add()"#
};

pub fn get_contract_address_state_entry_and_set_new_state_entry(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
_constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let dict_ptr = get_ptr_from_var_name(vars::ids::CONTRACT_STATE_CHANGES, vm, ids_data, ap_tracking)?;
let key = get_integer_from_var_name(vars::ids::CONTRACT_ADDRESS, vm, ids_data, ap_tracking)?;

get_state_entry_and_set_new_state_entry(dict_ptr, key.into_owned(), vm, exec_scopes, ids_data, ap_tracking)?;

Ok(())
}

pub const CHECK_IS_DEPRECATED: &str =
"is_deprecated = 1 if ids.execution_context.class_hash in __deprecated_class_hashes else 0";
pub fn check_is_deprecated(
Expand Down
14 changes: 12 additions & 2 deletions src/hints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type HintImpl = fn(
&HashMap<String, Felt252>,
) -> Result<(), HintError>;

static HINTS: [(&str, HintImpl); 87] = [
static HINTS: [(&str, HintImpl); 91] = [
(INITIALIZE_CLASS_HASHES, initialize_class_hashes),
(INITIALIZE_STATE_CHANGES, initialize_state_changes),
(IS_N_GE_TWO, is_n_ge_two),
Expand Down Expand Up @@ -86,7 +86,17 @@ static HINTS: [(&str, HintImpl); 87] = [
(execution::ENTER_SYSCALL_SCOPES, execution::enter_syscall_scopes),
(execution::EXIT_CALL, execution::exit_call),
(execution::GEN_SIGNATURE_ARG, execution::gen_signature_arg),
(execution::GET_STATE_ENTRY, execution::get_state_entry),
(execution::GET_CONTRACT_ADDRESS_STATE_ENTRY, execution::get_contract_address_state_entry),
(execution::GET_CONTRACT_ADDRESS_STATE_ENTRY_2, execution::get_contract_address_state_entry),
(
execution::GET_BLOCK_HASH_CONTRACT_ADDRESS_STATE_ENTRY_AND_SET_NEW_STATE_ENTRY,
execution::get_block_hash_contract_address_state_entry_and_set_new_state_entry,
),
(execution::GET_CONTRACT_ADDRESS_STATE_ENTRY, execution::get_contract_address_state_entry_and_set_new_state_entry),
(
execution::GET_CONTRACT_ADDRESS_STATE_ENTRY_2,
execution::get_contract_address_state_entry_and_set_new_state_entry,
),
(execution::IS_DEPRECATED, execution::is_deprecated),
(execution::IS_REVERTED, execution::is_reverted),
(execution::LOAD_NEXT_TX, execution::load_next_tx),
Expand Down
33 changes: 0 additions & 33 deletions src/hints/unimplemented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@ const CACHE_CONTRACT_STORAGE: &str = indoc! {r#"
assert ids.value == value, "Inconsistent storage value.""#
};

#[allow(unused)]
const FETCH_STATE_ENTRY: &str = indoc! {r#"
# Fetch a state_entry in this hint. Validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
ids.BLOCK_HASH_CONTRACT_ADDRESS]
ids.new_state_entry = segments.add()"#
};

#[allow(unused)]
const SET_INITIAL_STATE_UPDATES_PTR: &str = indoc! {r#"
# This hint shouldn't be whitelisted.
Expand Down Expand Up @@ -262,14 +254,6 @@ const SPLIT_DESCEND: &str = "ids.length, ids.word = descend";
const HEIGHT_IS_ZERO_OR_LEN_NODE_PREIMAGE_IS_TWO: &str =
"memory[ap] = 1 if ids.height == 0 or len(preimage[ids.node]) == 2 else 0";

#[allow(unused)]
const FETCH_STATE_ENTRY_3: &str = indoc! {r#"
# Fetch a state_entry in this hint and validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
ids.contract_address
]"#
};

#[allow(unused)]
const ENTER_SCOPE_NEW_TREE: &str = indoc! {r#"
new_node = node
Expand Down Expand Up @@ -335,13 +319,6 @@ const CHECK_RETURN_VALUE_2: &str = indoc! {r#"
assert expected == actual, f'Return value mismatch; expected={expected}, actual={actual}.'"#
};

#[allow(unused)]
const FETCH_STATE_ENTRY_4: &str = indoc! {r#"
# Fetch a state_entry in this hint and validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[ids.contract_address]
ids.new_state_entry = segments.add()"#
};

#[allow(unused)]
const BUILD_DESCENT_MAP: &str = indoc! {r#"
from starkware.cairo.common.patricia_utils import canonic, patricia_guess_descents
Expand Down Expand Up @@ -422,16 +399,6 @@ const START_TX_2: &str = indoc! {r#"
const GET_SEQUENCER_ADDRESS: &str =
"syscall_handler.get_sequencer_address(segments=segments, syscall_ptr=ids.syscall_ptr)";

#[allow(unused)]
const FETCH_STATE_ENTRY_5: &str = indoc! {r#"
# Fetch a state_entry in this hint and validate it in the update that comes next.
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
ids.contract_address
]
ids.new_state_entry = segments.add()"#
};

#[allow(unused)]
const ENTER_SCOPE_RIGHT_CHILD: &str = "vm_enter_scope(dict(node=right_child, **common_args))";

Expand Down
4 changes: 3 additions & 1 deletion src/hints/vars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ pub mod scopes {
}

pub mod ids {
pub const BLOCK_HASH_CONTRACT_ADDRESS: &str = "BLOCK_HASH_CONTRACT_ADDRESS";
pub const COMPILED_CLASS: &str = "compiled_class";
pub const COMPILED_CLASS_FACT: &str = "compiled_class_fact";
pub const CONTRACT_STATE_CHANGES: &str = "contract_state_changes";
pub const CONTRACT_ADDRESS: &str = "contract_address";
pub const CONTRACT_STATE_CHANGES: &str = "contract_state_changes";
pub const DEPRECATED_TX_INFO: &str = "deprecated_tx_info";
pub const EDGE: &str = "edge";
pub const FINAL_ROOT: &str = "final_root";
Expand All @@ -21,6 +22,7 @@ pub mod ids {
pub const IS_ON_CURVE: &str = "is_on_curve";
pub const MERKLE_HEIGHT: &str = "MERKLE_HEIGHT";
pub const N: &str = "n";
pub const NEW_STATE_ENTRY: &str = "new_state_entry";
pub const NODE: &str = "node";
pub const OS_CONTEXT: &str = "os_context";
pub const REQUEST: &str = "request";
Expand Down

0 comments on commit f41c64e

Please sign in to comment.