from starkware.cairo.common.cairo_builtins import HashBuiltin from starkware.cairo.common.hash_state import ( HashState, hash_finalize, hash_init, hash_update, hash_update_single, hash_update_with_hashchain, ) from starkware.cairo.common.math import assert_lt_felt from starkware.cairo.common.registers import get_fp_and_pc const DEPRECATED_COMPILED_CLASS_VERSION = 0; struct DeprecatedContractEntryPoint { // A field element that encodes the signature of the called function. selector: felt, // The offset of the instruction that should be called within the contract bytecode. offset: felt, } struct DeprecatedCompiledClass { compiled_class_version: felt, // The length and pointer to the external entry point table of the contract. n_external_functions: felt, external_functions: DeprecatedContractEntryPoint*, // The length and pointer to the L1 handler entry point table of the contract. n_l1_handlers: felt, l1_handlers: DeprecatedContractEntryPoint*, // The length and pointer to the constructor entry point table of the contract. n_constructors: felt, constructors: DeprecatedContractEntryPoint*, n_builtins: felt, // 'builtin_list' is a continuous memory segment containing the ASCII encoding of the (ordered) // builtins used by the program. builtin_list: felt*, // The hinted_class_hash field should be set to the starknet_keccak of the // contract program, including its hints. However the OS does not validate that. // This field may be used by the operator to differentiate between contract classes that // differ only in the hints. // This field is included in the hash of the ContractClass to simplify the implementation. hinted_class_hash: felt, // The length and pointer of the bytecode. bytecode_length: felt, bytecode_ptr: felt*, } // Checks that the list of selectors is sorted. func deprecated_validate_entry_points{range_check_ptr}( n_entry_points: felt, entry_points: DeprecatedContractEntryPoint* ) { if (n_entry_points == 0) { return (); } return deprecated_validate_entry_points_inner( n_entry_points=n_entry_points - 1, entry_points=&entry_points[1], prev_selector=entry_points[0].selector, ); } // Inner function for deprecated_validate_entry_points. func deprecated_validate_entry_points_inner{range_check_ptr}( n_entry_points: felt, entry_points: DeprecatedContractEntryPoint*, prev_selector ) { if (n_entry_points == 0) { return (); } assert_lt_felt(prev_selector, entry_points.selector); return deprecated_validate_entry_points_inner( n_entry_points=n_entry_points - 1, entry_points=&entry_points[1], prev_selector=entry_points[0].selector, ); } func deprecated_compiled_class_hash{hash_ptr: HashBuiltin*}( compiled_class: DeprecatedCompiledClass* ) -> (hash: felt) { let (hash_state_ptr: HashState*) = hash_init(); let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=compiled_class.compiled_class_version ); // Hash external entry points. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=compiled_class.external_functions, data_length=compiled_class.n_external_functions * DeprecatedContractEntryPoint.SIZE, ); // Hash L1 handler entry points. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=compiled_class.l1_handlers, data_length=compiled_class.n_l1_handlers * DeprecatedContractEntryPoint.SIZE, ); // Hash constructor entry points. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=compiled_class.constructors, data_length=compiled_class.n_constructors * DeprecatedContractEntryPoint.SIZE, ); // Hash builtins. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=compiled_class.builtin_list, data_length=compiled_class.n_builtins, ); // Hash hinted_class_hash. let (hash_state_ptr) = hash_update_single( hash_state_ptr=hash_state_ptr, item=compiled_class.hinted_class_hash ); // Hash bytecode. let (hash_state_ptr) = hash_update_with_hashchain( hash_state_ptr=hash_state_ptr, data_ptr=compiled_class.bytecode_ptr, data_length=compiled_class.bytecode_length, ); let (hash: felt) = hash_finalize(hash_state_ptr=hash_state_ptr); return (hash=hash); } // A list entry that maps a hash to the corresponding compiled classes. struct DeprecatedCompiledClassFact { // The hash of the compiled class. This member should be first, so that we can lookup items // with the hash as key, using find_element(). hash: felt, compiled_class: DeprecatedCompiledClass*, } // Loads the compiled classes from the 'os_input' hint variable. // Returns DeprecatedCompiledClassFact list that maps a hash to a DeprecatedCompiledClass. func deprecated_load_compiled_class_facts{pedersen_ptr: HashBuiltin*, range_check_ptr}() -> ( n_compiled_class_facts: felt, compiled_class_facts: DeprecatedCompiledClassFact* ) { alloc_locals; local n_compiled_class_facts; local compiled_class_facts: DeprecatedCompiledClassFact*; %{ # Creates a set of deprecated class hashes to distinguish calls to deprecated entry points. __deprecated_class_hashes=set(os_input.deprecated_compiled_classes.keys()) ids.compiled_class_facts = segments.add() ids.n_compiled_class_facts = len(os_input.deprecated_compiled_classes) vm_enter_scope({ 'compiled_class_facts': iter(os_input.deprecated_compiled_classes.items()), }) %} deprecated_load_compiled_class_facts_inner( n_compiled_class_facts=n_compiled_class_facts, compiled_class_facts=compiled_class_facts ); %{ vm_exit_scope() %} return ( n_compiled_class_facts=n_compiled_class_facts, compiled_class_facts=compiled_class_facts ); } // Loads 'n_compiled_class_facts' from the hint 'compiled_class_facts' and appends the // corresponding DeprecatedCompiledClassFact to compiled_class_facts. func deprecated_load_compiled_class_facts_inner{pedersen_ptr: HashBuiltin*, range_check_ptr}( n_compiled_class_facts, compiled_class_facts: DeprecatedCompiledClassFact* ) { if (n_compiled_class_facts == 0) { return (); } alloc_locals; let compiled_class_fact = compiled_class_facts; let compiled_class = compiled_class_fact.compiled_class; // Fetch contract data form hints. %{ from starkware.starknet.core.os.contract_class.deprecated_class_hash import ( get_deprecated_contract_class_struct, ) compiled_class_hash, compiled_class = next(compiled_class_facts) cairo_contract = get_deprecated_contract_class_struct( identifiers=ids._context.identifiers, contract_class=compiled_class) ids.compiled_class = segments.gen_arg(cairo_contract) %} assert compiled_class.compiled_class_version = DEPRECATED_COMPILED_CLASS_VERSION; deprecated_validate_entry_points( n_entry_points=compiled_class.n_external_functions, entry_points=compiled_class.external_functions, ); deprecated_validate_entry_points( n_entry_points=compiled_class.n_l1_handlers, entry_points=compiled_class.l1_handlers ); let (hash) = deprecated_compiled_class_hash{hash_ptr=pedersen_ptr}(compiled_class); compiled_class_fact.hash = hash; %{ from starkware.python.utils import from_bytes computed_hash = ids.compiled_class_fact.hash expected_hash = compiled_class_hash assert computed_hash == expected_hash, ( "Computed compiled_class_hash is inconsistent with the hash in the os_input. " f"Computed hash = {computed_hash}, Expected hash = {expected_hash}.") vm_load_program(compiled_class.program, ids.compiled_class.bytecode_ptr) %} return deprecated_load_compiled_class_facts_inner( n_compiled_class_facts=n_compiled_class_facts - 1, compiled_class_facts=compiled_class_facts + DeprecatedCompiledClassFact.SIZE, ); }