Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(hints): get_block_mapping #38

Merged
merged 1 commit into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/setup-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ cairo-compile tests/programs/bad_output.cairo --output build/programs/bad_output
cairo-compile tests/programs/fact.cairo --output build/programs/fact.json
cairo-compile tests/programs/load_deprecated_class.cairo --output build/programs/load_deprecated_class.json --cairo_path cairo-lang/src
cairo-compile tests/programs/initialize_state_changes.cairo --output build/programs/initialize_state_changes.json --cairo_path cairo-lang/src
cairo-compile tests/programs/get_block_mapping.cairo --output build/programs/get_block_mapping.json --cairo_path cairo-lang/src

# compile os with debug info
cairo-compile cairo-lang/src/starkware/starknet/core/os/os.cairo --output build/os_debug.json --cairo_path cairo-lang/src
Expand Down
36 changes: 35 additions & 1 deletion src/hints/block_context.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use core::panic;
use std::any::Any;
use std::collections::hash_map::IntoIter;
use std::collections::HashMap;

use blockifier::block_context::BlockContext;
use cairo_felt::Felt252;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{insert_value_from_var_name, insert_value_into_ap};
use cairo_vm::hint_processor::builtin_hint_processor::dict_manager::Dictionary;
use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{
get_ptr_from_var_name, insert_value_from_var_name, insert_value_into_ap,
};
use cairo_vm::hint_processor::hint_processor_definition::HintReference;
use cairo_vm::serde::deserialize_program::ApTracking;
use cairo_vm::types::exec_scope::ExecutionScopes;
Expand Down Expand Up @@ -183,3 +187,33 @@ pub fn sequencer_address(
MaybeRelocatable::Int(Felt252::from_bytes_be(os_input.general_config.sequencer_address.0.key().bytes())),
)
}

/// Implements hint:
///
/// ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
/// ids.BLOCK_HASH_CONTRACT_ADDRESS
/// ]
pub fn get_block_mapping(
vm: &mut VirtualMachine,
exec_scopes: &mut ExecutionScopes,
ids_data: &HashMap<String, HintReference>,
ap_tracking: &ApTracking,
constants: &HashMap<String, Felt252>,
) -> Result<(), HintError> {
let key = constants
.get("starkware.starknet.core.os.constants.BLOCK_HASH_CONTRACT_ADDRESS")
.expect("BLOCK_HASH_CONTRACT_ADDRESS should be in the context");
let dict_ptr = get_ptr_from_var_name("contract_state_changes", vm, ids_data, ap_tracking)?;
// def get_dict(self, dict_ptr) -> dict:
// Gets the python dict that corresponds to dict_ptr.
// return self.get_tracker(dict_ptr).data
let val = match exec_scopes.get_dict_manager()?.borrow().get_tracker(dict_ptr)?.data.clone() {
Dictionary::SimpleDictionary(dict) => {
dict.get(&MaybeRelocatable::Int(key.clone())).expect("State changes dictionnary shouldn't be None").clone()
}
Dictionary::DefaultDictionary { dict: _d, default_value: _v } => {
panic!("State changes dict shouldn't be a default dict")
}
};
insert_value_from_var_name("state_entry", val, vm, ids_data, ap_tracking)
}
3 changes: 3 additions & 0 deletions src/hints/hints_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,6 @@ pub const INITIALIZE_STATE_CHANGES: &str = "from starkware.python.utils import f
os_input.contracts.items()\n}";

pub const INITIALIZE_CLASS_HASHES: &str = "initial_dict = os_input.class_hash_to_compiled_class_hash";

pub const GET_BLOCK_MAPPING: &str =
"ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[\n ids.BLOCK_HASH_CONTRACT_ADDRESS\n]";
26 changes: 25 additions & 1 deletion tests/hints.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod common;

use std::fs;
use std::rc::Rc;

Expand All @@ -10,7 +11,9 @@ use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::*;
use common::load_input;
use common::utils::check_output_vs_python;
use rstest::{fixture, rstest};
use snos::hints::block_context::{load_deprecated_class_facts, load_deprecated_inner, sequencer_address};
use snos::hints::block_context::{
get_block_mapping, load_deprecated_class_facts, load_deprecated_inner, sequencer_address,
};
use snos::hints::hints_raw::*;
use snos::hints::{check_deprecated_class_hash, initialize_class_hashes, initialize_state_changes, starknet_os_input};
use snos::io::StarknetOsInput;
Expand Down Expand Up @@ -88,3 +91,24 @@ fn initialize_state_changes_test(mut os_input_hint_processor: BuiltinHintProcess
);
check_output_vs_python(run_output, program, true);
}

#[rstest]
fn get_block_mapping_test(mut os_input_hint_processor: BuiltinHintProcessor) {
let program = "build/programs/get_block_mapping.json";

let initialize_state_changes_hint = HintFunc(Box::new(initialize_state_changes));
os_input_hint_processor.add_hint(String::from(INITIALIZE_STATE_CHANGES), Rc::new(initialize_state_changes_hint));

let initialize_class_hashes_hint = HintFunc(Box::new(initialize_class_hashes));
os_input_hint_processor.add_hint(String::from(INITIALIZE_CLASS_HASHES), Rc::new(initialize_class_hashes_hint));

let get_block_mapping_hint = HintFunc(Box::new(get_block_mapping));
os_input_hint_processor.add_hint(String::from(GET_BLOCK_MAPPING), Rc::new(get_block_mapping_hint));

let run_output = cairo_run(
&fs::read(program).unwrap(),
&CairoRunConfig { layout: "starknet", relocate_mem: true, trace_enabled: true, ..Default::default() },
&mut os_input_hint_processor,
);
check_output_vs_python(run_output, program, true);
}
61 changes: 61 additions & 0 deletions tests/programs/get_block_mapping.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
%builtins output

from starkware.cairo.common.alloc import alloc
from starkware.cairo.common.segments import relocate_segment
from starkware.starknet.core.os.output import OsCarriedOutputs
from starkware.cairo.common.dict import dict_new, dict_read
from starkware.cairo.common.dict_access import DictAccess
from starkware.starknet.core.os.state import StateEntry
from starkware.cairo.common.serialize import serialize_word

from starkware.starknet.core.os.constants import BLOCK_HASH_CONTRACT_ADDRESS

func main{output_ptr: felt*}() {
alloc_locals;

let (initial_carried_outputs: OsCarriedOutputs*) = alloc();
%{
from starkware.starknet.core.os.os_input import StarknetOsInput
os_input = StarknetOsInput.load(data=program_input)
ids.initial_carried_outputs.messages_to_l1 = segments.add_temp_segment()
ids.initial_carried_outputs.messages_to_l2 = segments.add_temp_segment()
%}

%{
from starkware.python.utils import from_bytes
initial_dict = {
address: segments.gen_arg(
(from_bytes(contract.contract_hash), segments.add(), contract.nonce))
for address, contract in os_input.contracts.items()
}
%}

// A dictionary from contract address to a dict of storage changes of type StateEntry.
let (contract_state_changes: DictAccess*) = dict_new();

%{ initial_dict = os_input.class_hash_to_compiled_class_hash %}

let (state_entry: StateEntry*) = dict_read{dict_ptr=contract_state_changes}(
key=1470089414715992704702781317133162679047468004062084455026636858461958198968
);

assert state_entry.nonce = 2;

relocate_segment(src_ptr=initial_carried_outputs.messages_to_l1, dest_ptr=output_ptr);
relocate_segment(src_ptr=initial_carried_outputs.messages_to_l2, dest_ptr=output_ptr);
// Import this from starkware.starknet.core.os.constants import BLOCK_HASH_CONTRACT_ADDRESS
// When it works in the rust VM
local state_entry: StateEntry*;
%{
ids.state_entry = __dict_manager.get_dict(ids.contract_state_changes)[
ids.BLOCK_HASH_CONTRACT_ADDRESS
]
%}
assert [output_ptr] = state_entry.nonce;
assert [output_ptr + 1] = state_entry.class_hash;
let output_ptr = output_ptr + 2;
return ();
}