diff --git a/CHANGELOG.md b/CHANGELOG.md index a8c10f0fbc..287f86cae3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* fix(breaking): Match constants by full path [#2192](https://github.com/lambdaclass/cairo-vm/pull/2192) + #### [2.5.0] - 2025-09-11 * breaking: Store constants in Hint Data [#2191](https://github.com/lambdaclass/cairo-vm/pull/2191) diff --git a/cairo_programs/constant_collision.cairo b/cairo_programs/constant_collision.cairo new file mode 100644 index 0000000000..1d74bd393f --- /dev/null +++ b/cairo_programs/constant_collision.cairo @@ -0,0 +1,41 @@ +%builtins range_check + +from starkware.cairo.common.math import assert_le +from starkware.cairo.common.math import split_felt + +func override_constants{range_check_ptr}() { + const MAX_HIGH = -1; + const MAX_LOW = -1; + return (); +} +func split_felt_ok{range_check_ptr}(value) -> (high: felt, low: felt) { + const MAX_HIGH = (-1) / 2 ** 128; + const MAX_LOW = 0; + let low = [range_check_ptr]; + let high = [range_check_ptr + 1]; + let range_check_ptr = range_check_ptr + 2; + + %{ + from starkware.cairo.common.math_utils import assert_integer + assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128 + assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW + assert_integer(ids.value) + ids.low = ids.value & ((1 << 128) - 1) + ids.high = ids.value >> 128 + %} + + assert value = high * (2 ** 128) + low; + if (high == MAX_HIGH) { + assert_le(low, MAX_LOW); + } else { + assert_le(high, MAX_HIGH - 1); + } + return (high=high, low=low); +} + +func main{range_check_ptr: felt}() { + let (m, n) = split_felt_ok(5784800237655953878877368326340059594760); + assert m = 17; + assert n = 8; + return (); +} diff --git a/fuzzer/Cargo.lock b/fuzzer/Cargo.lock index 8d9373664e..5ac4486ae5 100644 --- a/fuzzer/Cargo.lock +++ b/fuzzer/Cargo.lock @@ -69,6 +69,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -78,12 +87,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - [[package]] name = "byteorder" version = "1.5.0" @@ -92,7 +95,7 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cairo-vm" -version = "2.0.0" +version = "2.4.0" dependencies = [ "anyhow", "arbitrary", @@ -118,7 +121,6 @@ dependencies = [ "starknet-crypto", "starknet-types-core", "thiserror", - "wasm-bindgen", "zip", ] @@ -407,12 +409,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "log" -version = "0.4.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" - [[package]] name = "lru" version = "0.12.5" @@ -809,9 +805,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "starknet-crypto" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039a3bad70806b494c9e6b21c5238a6c8a373d66a26071859deb0ccca6f93634" +checksum = "1004a16c25dc6113c19d4f9d0c19ff97d85804829894bba22c0d0e9e7b249812" dependencies = [ "crypto-bigint", "hex", @@ -828,26 +824,29 @@ dependencies = [ [[package]] name = "starknet-curve" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcde6bd74269b8161948190ace6cf069ef20ac6e79cd2ba09b320efa7500b6de" +checksum = "22c898ae81b6409532374cf237f1bd752d068b96c6ad500af9ebbd0d9bb712f6" dependencies = [ "starknet-types-core", ] [[package]] name = "starknet-types-core" -version = "0.1.7" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1b9e01ccb217ab6d475c5cda05dbb22c30029f7bb52b192a010a00d77a3d74" +checksum = "5fa3d91e38f091dbc543d33589eb7716bed2a8eb1c20879e484561977832b60a" dependencies = [ "arbitrary", + "blake2", + "digest", "lambdaworks-crypto", "lambdaworks-math", "num-bigint", "num-integer", "num-traits", "serde", + "zeroize", ] [[package]] @@ -946,60 +945,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - [[package]] name = "windows-targets" version = "0.52.6" diff --git a/hint_accountant/src/main.rs b/hint_accountant/src/main.rs index 9483bd4168..12d9dba572 100644 --- a/hint_accountant/src/main.rs +++ b/hint_accountant/src/main.rs @@ -51,11 +51,12 @@ fn run() { } let mut vm = VirtualMachine::new(false, false); let mut hint_executor = BuiltinHintProcessor::new_empty(); - let (ap_tracking_data, reference_ids, references, mut exec_scopes) = ( + let (ap_tracking_data, reference_ids, references, mut exec_scopes, accessible_scopes) = ( ApTracking::default(), HashMap::new(), Vec::new(), ExecutionScopes::new(), + Vec::new(), ); let missing_hints: HashSet<_> = whitelists .into_iter() @@ -69,6 +70,7 @@ fn run() { &reference_ids, &references, Default::default(), + &accessible_scopes, ) .expect("this implementation is infallible"); matches!( diff --git a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index c3cab5b58b..cb22944e75 100644 --- a/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/vm/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -23,6 +23,7 @@ use super::{ pack::*, }, }; +use crate::serde::deserialize_program::Identifier; use crate::Felt252; use crate::{ hint_processor::builtin_hint_processor::secp::secp_utils::{SECP256R1_ALPHA, SECP256R1_P}, @@ -132,7 +133,8 @@ pub struct HintProcessorData { pub code: String, pub ap_tracking: ApTracking, pub ids_data: HashMap, - pub constants: Rc>, + pub identifiers: Rc>, + pub accessible_scopes: Vec, } impl HintProcessorData { @@ -141,7 +143,8 @@ impl HintProcessorData { code, ap_tracking: ApTracking::default(), ids_data, - constants: Default::default(), + identifiers: Default::default(), + accessible_scopes: Default::default(), } } } @@ -193,15 +196,28 @@ impl HintProcessorLogic for BuiltinHintProcessor { let hint_data = hint_data .downcast_ref::() .ok_or(HintError::WrongHintData)?; - let constants = hint_data.constants.as_ref(); if let Some(hint_func) = self.extra_hints.get(&hint_data.code) { + let constants = hint_data + .identifiers + .as_ref() + .clone() + .into_iter() + .filter_map(|(key, identifier)| { + if identifier.type_? == "const" { + Some((key, identifier.value?)) + } else { + None + } + }) + .collect(); + return hint_func.0( vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &constants, ); } match &*hint_data.code { @@ -215,19 +231,28 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), hint_code::ASSERT_LE_FELT_EXCLUDED_2 => assert_le_felt_excluded_2(exec_scopes), hint_code::ASSERT_LE_FELT_EXCLUDED_1 => assert_le_felt_excluded_1(vm, exec_scopes), hint_code::ASSERT_LE_FELT_EXCLUDED_0 => assert_le_felt_excluded_0(vm, exec_scopes), hint_code::IS_LE_FELT => is_le_felt(vm, &hint_data.ids_data, &hint_data.ap_tracking), - hint_code::ASSERT_250_BITS => { - assert_250_bit(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } + hint_code::ASSERT_250_BITS => assert_250_bit( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), hint_code::IS_250_BITS => is_250_bits(vm, &hint_data.ids_data, &hint_data.ap_tracking), - hint_code::IS_ADDR_BOUNDED => { - is_addr_bounded(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } + hint_code::IS_ADDR_BOUNDED => is_addr_bounded( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), hint_code::IS_POSITIVE => is_positive(vm, &hint_data.ids_data, &hint_data.ap_tracking), hint_code::SPLIT_INT_ASSERT_RANGE => { split_int_assert_range(vm, &hint_data.ids_data, &hint_data.ap_tracking) @@ -265,9 +290,13 @@ impl HintProcessorLogic for BuiltinHintProcessor { &hint_data.ap_tracking, "continue_loop", ), - hint_code::SPLIT_FELT => { - split_felt(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } + hint_code::SPLIT_FELT => split_felt( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), hint_code::UNSIGNED_DIV_REM => { unsigned_div_rem(vm, &hint_data.ids_data, &hint_data.ap_tracking) } @@ -443,9 +472,13 @@ impl HintProcessorLogic for BuiltinHintProcessor { hint_code::UINT256_EXPANDED_UNSIGNED_DIV_REM => { uint256_expanded_unsigned_div_rem(vm, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::BIGINT_TO_UINT256 => { - bigint_to_uint256(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } + hint_code::BIGINT_TO_UINT256 => bigint_to_uint256( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), hint_code::IS_ZERO_PACK_V1 | hint_code::IS_ZERO_PACK_V2 => { is_zero_pack(vm, exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking) } @@ -499,7 +532,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), hint_code::EC_NEGATE => ec_negate_import_secp_p( vm, @@ -657,19 +691,22 @@ impl HintProcessorLogic for BuiltinHintProcessor { vm, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), hint_code::SHA256_MAIN_CONSTANT_INPUT_LENGTH => sha256_main_constant_input_length( vm, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), hint_code::SHA256_MAIN_ARBITRARY_INPUT_LENGTH => sha256_main_arbitrary_input_length( vm, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), hint_code::SHA256_INPUT => { sha256_input(vm, &hint_data.ids_data, &hint_data.ap_tracking) @@ -685,21 +722,40 @@ impl HintProcessorLogic for BuiltinHintProcessor { vm, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ) } hint_code::BLOCK_PERMUTATION | hint_code::BLOCK_PERMUTATION_WHITELIST_V1 => { - block_permutation_v1(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } - hint_code::BLOCK_PERMUTATION_WHITELIST_V2 => { - block_permutation_v2(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } - hint_code::CAIRO_KECCAK_FINALIZE_V1 => { - cairo_keccak_finalize_v1(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } - hint_code::CAIRO_KECCAK_FINALIZE_V2 => { - cairo_keccak_finalize_v2(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) + block_permutation_v1( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ) } + hint_code::BLOCK_PERMUTATION_WHITELIST_V2 => block_permutation_v2( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), + hint_code::CAIRO_KECCAK_FINALIZE_V1 => cairo_keccak_finalize_v1( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), + hint_code::CAIRO_KECCAK_FINALIZE_V2 => cairo_keccak_finalize_v2( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), hint_code::FAST_EC_ADD_ASSIGN_NEW_X => fast_ec_add_assign_new_x( vm, exec_scopes, @@ -761,9 +817,13 @@ impl HintProcessorLogic for BuiltinHintProcessor { hint_code::SPLIT_INPUT_15 => { split_input(vm, &hint_data.ids_data, &hint_data.ap_tracking, 15, 5) } - hint_code::SPLIT_N_BYTES => { - split_n_bytes(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } + hint_code::SPLIT_N_BYTES => split_n_bytes( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), hint_code::SPLIT_OUTPUT_MID_LOW_HIGH => { split_output_mid_low_high(vm, &hint_data.ids_data, &hint_data.ap_tracking) } @@ -796,9 +856,13 @@ impl HintProcessorLogic for BuiltinHintProcessor { hint_code::UINT384_SPLIT_128 => { uint384_split_128(vm, &hint_data.ids_data, &hint_data.ap_tracking) } - hint_code::ADD_NO_UINT384_CHECK => { - add_no_uint384_check(vm, &hint_data.ids_data, &hint_data.ap_tracking, constants) - } + hint_code::ADD_NO_UINT384_CHECK => add_no_uint384_check( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + &hint_data.identifiers, + &hint_data.accessible_scopes, + ), hint_code::UINT384_SQRT => { uint384_sqrt(vm, &hint_data.ids_data, &hint_data.ap_tracking) } @@ -872,7 +936,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { vm, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ) } #[cfg(feature = "test_utils")] @@ -889,7 +954,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { vm, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, exec_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] @@ -898,7 +964,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] cairo0_hints::COMPUTE_IDS_HIGH_LOW => cairo0_hints::compute_ids_high_low( @@ -906,7 +973,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] cairo0_hints::SECP_DOUBLE_ASSIGN_NEW_X => cairo0_hints::secp_double_assign_new_x( @@ -914,7 +982,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, SECP256R1_P.magnitude(), ), #[cfg(feature = "cairo-0-secp-hints")] @@ -923,7 +992,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, &CAIRO_PRIME, ), #[cfg(feature = "cairo-0-secp-hints")] @@ -932,7 +1002,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] cairo0_hints::COMPUTE_VALUE_DIV_MOD => cairo0_hints::compute_value_div_mod( @@ -940,7 +1011,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] cairo0_hints::GENERATE_NIBBLES => cairo0_hints::generate_nibbles( @@ -948,7 +1020,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] @@ -957,7 +1030,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] cairo0_hints::IS_ON_CURVE_2 => cairo0_hints::is_on_curve_2( @@ -965,7 +1039,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] cairo0_hints::SECP_R1_GET_POINT_FROM_X => cairo0_hints::r1_get_point_from_x( @@ -973,7 +1048,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, SECP256R1_P.magnitude(), ), @@ -983,7 +1059,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, &CAIRO_PRIME, ), @@ -993,7 +1070,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-secp-hints")] cairo0_hints::SECP_REDUCE_X => cairo0_hints::reduce_x( @@ -1001,7 +1079,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), #[cfg(feature = "cairo-0-data-availability-hints")] super::kzg_da::WRITE_DIVMOD_SEGMENT => super::kzg_da::write_div_mod_segment( @@ -1009,7 +1088,8 @@ impl HintProcessorLogic for BuiltinHintProcessor { exec_scopes, &hint_data.ids_data, &hint_data.ap_tracking, - constants, + &hint_data.identifiers, + &hint_data.accessible_scopes, ), code => Err(HintError::UnknownHint(code.to_string().into_boxed_str())), diff --git a/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs b/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs index 202cba60a0..fe3376d301 100644 --- a/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs +++ b/vm/src/hint_processor/builtin_hint_processor/cairo_keccak/keccak_hints.rs @@ -1,8 +1,12 @@ -use crate::stdlib::{ - borrow::{Cow, ToOwned}, - boxed::Box, - collections::HashMap, - prelude::*, +use crate::{ + hint_processor::builtin_hint_processor::hint_utils::get_constant_from_var_name, + serde::deserialize_program::Identifier, + stdlib::{ + borrow::{Cow, ToOwned}, + boxed::Box, + collections::HashMap, + prelude::*, + }, }; use crate::{ hint_processor::{ @@ -23,21 +27,6 @@ use crate::{ }; use num_traits::ToPrimitive; -// Constants in package "starkware.cairo.common.cairo_keccak.keccak". -const BYTES_IN_WORD: &str = "starkware.cairo.common.cairo_keccak.keccak.BYTES_IN_WORD"; -const KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK: &str = - "starkware.cairo.common.cairo_keccak.keccak.KECCAK_FULL_RATE_IN_BYTES"; -const KECCAK_FULL_RATE_IN_BYTES_BUILTIN_KECCAK: &str = - "starkware.cairo.common.builtin_keccak.keccak.KECCAK_FULL_RATE_IN_BYTES"; - -const KECCAK_FULL_RATE_IN_BYTES: &str = "KECCAK_FULL_RATE_IN_BYTES"; - -const KECCAK_STATE_SIZE_FELTS: &str = - "starkware.cairo.common.cairo_keccak.keccak.KECCAK_STATE_SIZE_FELTS"; - -// Constants in package "starkware.cairo.common.cairo_keccak.packed_keccak". -const BLOCK_SIZE: &str = "starkware.cairo.common.cairo_keccak.packed_keccak.BLOCK_SIZE"; - /* Implements hint: %{ @@ -80,7 +69,8 @@ pub fn compare_bytes_in_word_nondet( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let n_bytes = get_integer_from_var_name("n_bytes", vm, ids_data, ap_tracking)?; let n_bytes = n_bytes.as_ref(); @@ -90,9 +80,8 @@ pub fn compare_bytes_in_word_nondet( // making value be 0 (if it can't convert then it's either negative, which can't be in Cairo memory // or too big, which also means n_bytes > BYTES_IN_WORD). The other option is to exctract // Felt252::from(BYTES_INTO_WORD) into a lazy_static! - let bytes_in_word = constants - .get(BYTES_IN_WORD) - .ok_or_else(|| HintError::MissingConstant(Box::new(BYTES_IN_WORD)))?; + let bytes_in_word = + get_constant_from_var_name("BYTES_IN_WORD", identifiers, accessible_scopes)?; let value = Felt252::from((n_bytes < bytes_in_word) as usize); insert_value_into_ap(vm, value) } @@ -109,15 +98,14 @@ pub fn compare_keccak_full_rate_in_bytes_nondet( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let n_bytes = get_integer_from_var_name("n_bytes", vm, ids_data, ap_tracking)?; let n_bytes = n_bytes.as_ref(); - let keccak_full_rate_in_bytes = constants - .get(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK) - .or_else(|| constants.get(KECCAK_FULL_RATE_IN_BYTES_BUILTIN_KECCAK)) - .ok_or_else(|| HintError::MissingConstant(Box::new(KECCAK_FULL_RATE_IN_BYTES)))?; + let keccak_full_rate_in_bytes = + get_constant_from_var_name("KECCAK_FULL_RATE_IN_BYTES", identifiers, accessible_scopes)?; let value = Felt252::from((n_bytes >= keccak_full_rate_in_bytes) as usize); insert_value_into_ap(vm, value) } @@ -147,11 +135,11 @@ pub(crate) fn block_permutation_v1( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { - let keccak_state_size_felts = constants - .get(KECCAK_STATE_SIZE_FELTS) - .ok_or_else(|| HintError::MissingConstant(Box::new(KECCAK_STATE_SIZE_FELTS)))?; + let keccak_state_size_felts = + get_constant_from_var_name("KECCAK_STATE_SIZE_FELTS", identifiers, accessible_scopes)?; if keccak_state_size_felts >= &Felt252::from(100_i32) { return Err(HintError::InvalidKeccakStateSizeFelt252s(Box::new( *keccak_state_size_felts, @@ -214,11 +202,11 @@ pub(crate) fn block_permutation_v2( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { - let keccak_state_size_felts = constants - .get(KECCAK_STATE_SIZE_FELTS) - .ok_or_else(|| HintError::MissingConstant(Box::new(KECCAK_STATE_SIZE_FELTS)))?; + let keccak_state_size_felts = + get_constant_from_var_name("KECCAK_STATE_SIZE_FELTS", identifiers, accessible_scopes)?; if keccak_state_size_felts >= &Felt252::from(100_i32) { return Err(HintError::InvalidKeccakStateSizeFelt252s(Box::new( *keccak_state_size_felts, @@ -250,15 +238,13 @@ fn cairo_keccak_finalize( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], block_size_limit: usize, ) -> Result<(), HintError> { - let keccak_state_size_felts = constants - .get(KECCAK_STATE_SIZE_FELTS) - .ok_or_else(|| HintError::MissingConstant(Box::new(KECCAK_STATE_SIZE_FELTS)))?; - let block_size = constants - .get(BLOCK_SIZE) - .ok_or_else(|| HintError::MissingConstant(Box::new(BLOCK_SIZE)))?; + let keccak_state_size_felts = + get_constant_from_var_name("KECCAK_STATE_SIZE_FELTS", identifiers, accessible_scopes)?; + let block_size = get_constant_from_var_name("BLOCK_SIZE", identifiers, accessible_scopes)?; if keccak_state_size_felts >= &Felt252::from(100_i32) { return Err(HintError::InvalidKeccakStateSizeFelt252s(Box::new( @@ -311,9 +297,17 @@ pub(crate) fn cairo_keccak_finalize_v1( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { - cairo_keccak_finalize(vm, ids_data, ap_tracking, constants, 10) + cairo_keccak_finalize( + vm, + ids_data, + ap_tracking, + identifiers, + accessible_scopes, + 10, + ) } /* Implements hint: @@ -332,9 +326,17 @@ pub(crate) fn cairo_keccak_finalize_v2( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { - cairo_keccak_finalize(vm, ids_data, ap_tracking, constants, 1000) + cairo_keccak_finalize( + vm, + ids_data, + ap_tracking, + identifiers, + accessible_scopes, + 1000, + ) } // Helper function to transform a vector of MaybeRelocatables into a vector @@ -366,7 +368,6 @@ pub fn u64_array_to_mayberelocatable_vec(array: &[u64]) -> Vec mod tests { use super::*; use crate::stdlib::string::ToString; - use crate::{ any_box, hint_processor::{ @@ -448,16 +449,19 @@ mod tests { run_context!(vm, 0, 1, 1); let ids_data = ids_data!["n_bytes"]; + let identifiers = HashMap::from([( + "starkware.cairo.common.cairo_keccak.keccak.KECCAK_FULL_RATE_IN_BYTES".to_string(), + const_identifier(136), + )]); + let accessible_scopes = vec!["starkware.cairo.common.cairo_keccak.keccak".to_string()]; assert_matches!( run_hint!( vm, ids_data, hint_code, exec_scopes_ref!(), - &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::from(136))] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ); @@ -477,16 +481,19 @@ mod tests { run_context!(vm, 0, 1, 1); let ids_data = ids_data!["n_bytes"]; + let identifiers = HashMap::from([( + "starkware.cairo.common.cairo_keccak.keccak.KECCAK_FULL_RATE_IN_BYTES".to_string(), + const_identifier(136), + )]); + let accessible_scopes = vec!["starkware.cairo.common.cairo_keccak.keccak".to_string()]; assert_matches!( run_hint!( vm, ids_data, hint_code, exec_scopes_ref!(), - &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::from(136))] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ); @@ -505,16 +512,19 @@ mod tests { run_context!(vm, 0, 1, 1); let ids_data = ids_data!["n_bytes"]; + let identifiers = HashMap::from([( + "starkware.cairo.common.cairo_keccak.keccak.KECCAK_FULL_RATE_IN_BYTES".to_string(), + const_identifier(136), + )]); + let accessible_scopes = vec!["starkware.cairo.common.cairo_keccak.keccak".to_string()]; assert_matches!( run_hint!( vm, ids_data, hint_code, exec_scopes_ref!(), - &[(KECCAK_FULL_RATE_IN_BYTES_CAIRO_KECCAK, Felt252::from(136))] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ); diff --git a/vm/src/hint_processor/builtin_hint_processor/excess_balance.rs b/vm/src/hint_processor/builtin_hint_processor/excess_balance.rs index 4c676053ce..247e56b944 100644 --- a/vm/src/hint_processor/builtin_hint_processor/excess_balance.rs +++ b/vm/src/hint_processor/builtin_hint_processor/excess_balance.rs @@ -1,6 +1,6 @@ use crate::{ hint_processor::hint_processor_definition::HintReference, - serde::deserialize_program::ApTracking, + serde::deserialize_program::{ApTracking, Identifier}, stdlib::collections::HashMap, types::{exec_scope::ExecutionScopes, relocatable::MaybeRelocatable}, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, @@ -262,13 +262,15 @@ pub fn excess_balance_hint( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], exec_scopes: &ExecutionScopes, ) -> Result<(), HintError> { // Fetch constants & variables let margin_check_type = get_integer_from_var_name("margin_check_type", vm, ids_data, ap_tracking)?; - let margin_check_initial = get_constant_from_var_name("MARGIN_CHECK_INITIAL", constants)?; + let margin_check_initial = + get_constant_from_var_name("MARGIN_CHECK_INITIAL", identifiers, accessible_scopes)?; let token_assets_value_d = get_integer_from_var_name("token_assets_value_d", vm, ids_data, ap_tracking)?; let account = get_integer_from_var_name("account", vm, ids_data, ap_tracking)?; @@ -593,7 +595,11 @@ mod tests { // SETUP let mut vm = vm!(); // CONSTANTS - let constants = HashMap::from([("MARGIN_CHECK_INITIAL".to_string(), Felt252::ONE)]); + let identifiers = HashMap::from([( + "__main__.MARGIN_CHECK_INITIAL".to_string(), + const_identifier(1), + )]); + let accessible_scopes = vec!["__main__".to_string()]; // IDS vm.segments = segments!( ((1, 0), 1), // ids.margin_check_type @@ -826,7 +832,8 @@ mod tests { &mut vm, &ids, &ApTracking::default(), - &constants, + &identifiers, + &accessible_scopes, &exec_scopes ) .is_ok()); @@ -935,7 +942,11 @@ mod tests { // SETUP let mut vm = vm!(); // CONSTANTS - let constants = HashMap::from([("MARGIN_CHECK_INITIAL".to_string(), Felt252::ONE)]); + let identifiers = HashMap::from([( + "__main__.MARGIN_CHECK_INITIAL".to_string(), + const_identifier(1), + )]); + let accessible_scopes = vec!["__main__".to_string()]; // IDS vm.segments = segments!( ((1, 0), 1), // ids.margin_check_type @@ -1192,7 +1203,8 @@ mod tests { &mut vm, &ids, &ApTracking::default(), - &constants, + &identifiers, + &accessible_scopes, &exec_scopes ) .is_ok()); diff --git a/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs index 1da3905e02..3bb66a96fc 100644 --- a/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/hint_utils.rs @@ -1,4 +1,8 @@ -use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; +use crate::stdlib::{ + boxed::Box, + collections::{HashMap, HashSet}, + prelude::*, +}; use crate::Felt252; @@ -9,7 +13,7 @@ use crate::hint_processor::hint_processor_utils::{ use crate::hint_processor::hint_processor_utils::{ get_integer_from_reference, get_maybe_relocatable_from_reference, }; -use crate::serde::deserialize_program::ApTracking; +use crate::serde::deserialize_program::{ApTracking, Identifier}; use crate::types::relocatable::MaybeRelocatable; use crate::types::relocatable::Relocatable; use crate::vm::errors::hint_errors::HintError; @@ -175,14 +179,51 @@ pub fn get_reference_from_var_name<'a>( } pub fn get_constant_from_var_name<'a>( - var_name: &'static str, - constants: &'a HashMap, + scoped_name: &str, + identifiers: &'a HashMap, + accessible_scopes: &[String], ) -> Result<&'a Felt252, HintError> { - constants - .iter() - .find(|(k, _)| k.rsplit('.').next() == Some(var_name)) - .map(|(_, n)| n) - .ok_or_else(|| HintError::MissingConstant(Box::new(var_name))) + // Inner scopes override outer scopes. + for scope in accessible_scopes.iter().rev() { + let full_path = format!("{}.{}", scope, scoped_name); + + let Some(mut identifier) = identifiers.get(&full_path) else { + continue; + }; + + let mut visited_aliases = HashSet::new(); + visited_aliases.insert(&full_path); + + // If the identifier is of alias type, we resolve the alias. + while identifier.type_.as_deref() == Some("alias") { + let destination = identifier + .destination + .as_ref() + .ok_or_else(|| HintError::UnknownIdentifierInternal)?; + + if !visited_aliases.insert(destination) { + return Err(HintError::CyclicAliasing); + } + + identifier = identifiers.get(destination).ok_or_else(|| { + HintError::UnknownIdentifier(destination.clone().into_boxed_str()) + })?; + } + + // As are only looking for constants, we ignore any other identifiers. + if identifier.type_.as_deref() != Some("const") { + continue; + } + + return identifier + .value + .as_ref() + .ok_or_else(|| HintError::UnknownIdentifierInternal); + } + + Err(HintError::UnknownIdentifier( + scoped_name.to_string().into_boxed_str(), + )) } #[cfg(test)] @@ -325,4 +366,79 @@ mod tests { Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value" ); } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_constant_from_var_name_valid() { + let accessible_scopes = &["scope1".to_string(), "scope1.scope2".to_string()]; + + let identifier = const_identifier(5); + + let identifiers = HashMap::from([( + "scope1.scope2.constant1.constant2".to_string(), + identifier.clone(), + )]); + + assert_eq!( + *get_constant_from_var_name("constant1.constant2", &identifiers, accessible_scopes) + .unwrap(), + Felt252::from(5) + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_constant_from_var_name_invalid() { + let accessible_scopes = &["scope1".to_string(), "scope1.scope2".to_string()]; + + let identifier = const_identifier(5); + + let identifiers = HashMap::from([( + "scope1.scope2.constant3.constant4".to_string(), + identifier.clone(), + )]); + + assert_matches!( + get_constant_from_var_name("constant1.constant2", &identifiers, accessible_scopes), + Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "constant1.constant2" + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_constant_from_var_name_with_alias() { + let accessible_scopes = &["scope1".to_string(), "scope1.scope2".to_string()]; + + let identifier = const_identifier(5); + let alias = alias_identifier("scope3.constant1"); + + let identifiers = HashMap::from([ + ("scope1.scope2.alias1".to_string(), alias.clone()), + ("scope3.constant1".to_string(), identifier.clone()), + ]); + + assert_eq!( + *get_constant_from_var_name("alias1", &identifiers, accessible_scopes).unwrap(), + Felt252::from(5) + ); + } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_constant_from_var_name_with_cyclic_alias() { + let accessible_scopes = &["scope1".to_string(), "scope1.scope2".to_string()]; + + let alias1 = alias_identifier("scope3.alias2"); + let alias2 = alias_identifier("scope1.scope2.alias1"); + + let identifiers = HashMap::from([ + ("scope1.scope2.alias1".to_string(), alias1.clone()), + ("scope3.alias2".to_string(), alias2.clone()), + ]); + + assert_matches!( + get_constant_from_var_name("alias1", &identifiers, accessible_scopes), + Err(HintError::CyclicAliasing) + ); + } } diff --git a/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs b/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs index b348df8a04..15c8db6b19 100644 --- a/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/keccak_utils.rs @@ -1,3 +1,4 @@ +use crate::serde::deserialize_program::Identifier; use crate::stdlib::{boxed::Box, cmp, collections::HashMap, prelude::*}; use crate::types::errors::math_errors::MathError; @@ -18,9 +19,7 @@ use num_integer::Integer; use num_traits::ToPrimitive; use sha3::{Digest, Keccak256}; -use super::hint_utils::insert_value_from_var_name; - -const BYTES_IN_WORD: &str = "starkware.cairo.common.builtin_keccak.keccak.BYTES_IN_WORD"; +use super::hint_utils::{get_constant_from_var_name, insert_value_from_var_name}; /* Implements hint: %{ @@ -239,17 +238,19 @@ pub fn split_n_bytes( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let n_bytes = get_integer_from_var_name("n_bytes", vm, ids_data, ap_tracking).and_then(|x| { x.to_u64() .ok_or_else(|| HintError::Math(MathError::Felt252ToU64Conversion(Box::new(x)))) })?; - let bytes_in_word = constants - .get(BYTES_IN_WORD) - .and_then(|x| x.to_u64()) - .ok_or_else(|| HintError::MissingConstant(Box::new(BYTES_IN_WORD)))?; + let bytes_in_word = + get_constant_from_var_name("BYTES_IN_WORD", identifiers, accessible_scopes)?; + let bytes_in_word = bytes_in_word + .to_u64() + .ok_or_else(|| MathError::Felt252ToU64Conversion(Box::new(*bytes_in_word)))?; let (high, low) = n_bytes.div_mod_floor(&bytes_in_word); insert_value_from_var_name( "n_words_to_copy", @@ -357,13 +358,21 @@ mod tests { vm.segments = segments![((1, 2), 17)]; vm.set_fp(3); let ids_data = ids_data!["n_words_to_copy", "n_bytes_left", "n_bytes"]; + + let identifiers = HashMap::from([( + "starkware.cairo.common.builtin_keccak.keccak.BYTES_IN_WORD".to_string(), + const_identifier(8), + )]); + let accessible_scopes = vec!["starkware.cairo.common.builtin_keccak.keccak".to_string()]; + assert_matches!( run_hint!( vm, ids_data, hint_code::SPLIT_N_BYTES, exec_scopes_ref!(), - &HashMap::from([(String::from(BYTES_IN_WORD), Felt252::from(8))]) + identifiers, + accessible_scopes ), Ok(()) ); @@ -376,13 +385,19 @@ mod tests { vm.segments = segments![((1, 0), 72057594037927938)]; vm.set_fp(4); let ids_data = ids_data!["output1", "output1_low", "output1_mid", "output1_high"]; + let identifiers = HashMap::from([( + "starkware.cairo.common.builtin_keccak.keccak.BYTES_IN_WORD".to_string(), + const_identifier(8), + )]); + let accessible_scopes = vec!["starkware.cairo.common.builtin_keccak.keccak".to_string()]; assert_matches!( run_hint!( vm, ids_data, hint_code::SPLIT_OUTPUT_MID_LOW_HIGH, exec_scopes_ref!(), - &HashMap::from([(String::from(BYTES_IN_WORD), Felt252::from(8))]) + identifiers, + accessible_scopes ), Ok(()) ); diff --git a/vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs b/vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs index 49bb8c348f..8a77644365 100644 --- a/vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs +++ b/vm/src/hint_processor/builtin_hint_processor/kzg_da/mod.rs @@ -3,7 +3,7 @@ use core::str::FromStr; use super::{hint_utils::get_relocatable_from_var_name, secp::bigint_utils::BigInt3}; use crate::{ hint_processor::hint_processor_definition::HintReference, - serde::deserialize_program::ApTracking, + serde::deserialize_program::{ApTracking, Identifier}, types::relocatable::MaybeRelocatable, utils::CAIRO_PRIME, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, @@ -44,7 +44,8 @@ pub fn write_div_mod_segment( _exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { let a = bls_pack( &BigInt3::from_var_name("a", vm, ids_data, ap_tracking)?, diff --git a/vm/src/hint_processor/builtin_hint_processor/math_utils.rs b/vm/src/hint_processor/builtin_hint_processor/math_utils.rs index eb65aed496..9fad48b918 100644 --- a/vm/src/hint_processor/builtin_hint_processor/math_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/math_utils.rs @@ -1,6 +1,7 @@ use crate::{ hint_processor::builtin_hint_processor::hint_utils::get_constant_from_var_name, math_utils::signed_felt, + serde::deserialize_program::Identifier, stdlib::{boxed::Box, collections::HashMap, prelude::*}, types::errors::math_errors::MathError, }; @@ -36,8 +37,6 @@ use super::{ uint256_utils::Uint256, }; -const ADDR_BOUND: &str = "starkware.starknet.common.storage.ADDR_BOUND"; - //Implements hint: memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1 pub fn is_nn( vm: &mut VirtualMachine, @@ -90,17 +89,13 @@ pub fn assert_le_felt( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { - const PRIME_OVER_3_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH"; - const PRIME_OVER_2_HIGH: &str = "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH"; - - let prime_over_3_high = constants - .get(PRIME_OVER_3_HIGH) - .ok_or_else(|| HintError::MissingConstant(Box::new(PRIME_OVER_3_HIGH)))?; - let prime_over_2_high = constants - .get(PRIME_OVER_2_HIGH) - .ok_or_else(|| HintError::MissingConstant(Box::new(PRIME_OVER_2_HIGH)))?; + let prime_over_3_high = + get_constant_from_var_name("PRIME_OVER_3_HIGH", identifiers, accessible_scopes)?; + let prime_over_2_high = + get_constant_from_var_name("PRIME_OVER_2_HIGH", identifiers, accessible_scopes)?; let a = get_integer_from_var_name("a", vm, ids_data, ap_tracking)?.to_biguint(); let b = get_integer_from_var_name("b", vm, ids_data, ap_tracking)?.to_biguint(); let range_check_ptr = get_ptr_from_var_name("range_check_ptr", vm, ids_data, ap_tracking)?; @@ -384,15 +379,16 @@ pub fn split_felt( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let assert = |b: bool, msg: &str| { b.then_some(()) .ok_or_else(|| HintError::AssertionFailed(msg.to_string().into_boxed_str())) }; let bound = pow2_const(128); - let max_high = get_constant_from_var_name("MAX_HIGH", constants)?; - let max_low = get_constant_from_var_name("MAX_LOW", constants)?; + let max_high = get_constant_from_var_name("MAX_HIGH", identifiers, accessible_scopes)?; + let max_low = get_constant_from_var_name("MAX_LOW", identifiers, accessible_scopes)?; assert( max_high < &bound && max_low < &bound, "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128", @@ -521,17 +517,12 @@ pub fn assert_250_bit( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { - const UPPER_BOUND: &str = "starkware.cairo.common.math.assert_250_bit.UPPER_BOUND"; - const SHIFT: &str = "starkware.cairo.common.math.assert_250_bit.SHIFT"; //Declare constant values - let upper_bound = constants - .get(UPPER_BOUND) - .map_or_else(|| get_constant_from_var_name("UPPER_BOUND", constants), Ok)?; - let shift = constants - .get(SHIFT) - .map_or_else(|| get_constant_from_var_name("SHIFT", constants), Ok)?; + let upper_bound = get_constant_from_var_name("UPPER_BOUND", identifiers, accessible_scopes)?; + let shift = get_constant_from_var_name("SHIFT", identifiers, accessible_scopes)?; let value = Felt252::from(&signed_felt(get_integer_from_var_name( "value", vm, @@ -577,14 +568,13 @@ pub fn is_addr_bounded( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?; - let addr_bound = constants - .get(ADDR_BOUND) - .ok_or_else(|| HintError::MissingConstant(Box::new(ADDR_BOUND)))? - .to_biguint(); + let addr_bound = + get_constant_from_var_name("ADDR_BOUND", identifiers, accessible_scopes)?.to_biguint(); let lower_bound = BigUint::one() << 250_usize; let upper_bound = BigUint::one() << 251_usize; @@ -916,15 +906,6 @@ mod tests { #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_assert_le_felt_valid() { - let mut constants = HashMap::new(); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_hex!("4000000000000088000000000000001"), - ); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_hex!("2AAAAAAAAAAAAB05555555555555556"), - ); let mut vm = vm_with_range_check!(); let mut exec_scopes = scope![("excluded", 1)]; //Initialize fp @@ -934,6 +915,17 @@ mod tests { add_segments!(vm, 1); //Create ids_data & hint_data let ids_data = ids_data!["a", "b", "range_check_ptr"]; + let identifiers = HashMap::from([ + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), + const_identifier(felt_hex!("4000000000000088000000000000001")), + ), + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), + const_identifier(felt_hex!("2AAAAAAAAAAAAB05555555555555556")), + ), + ]); + let accessible_scopes = vec!["starkware.cairo.common.math.assert_le_felt".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -941,7 +933,8 @@ mod tests { ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, - &constants + identifiers, + accessible_scopes ), Ok(()) ); @@ -1108,15 +1101,6 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_is_assert_le_felt_invalid() { let mut vm = vm_with_range_check!(); - let mut constants = HashMap::new(); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_hex!("4000000000000088000000000000001"), - ); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_hex!("2AAAAAAAAAAAAB05555555555555556"), - ); let mut exec_scopes = scope![("excluded", Felt252::ONE)]; //Initialize fp vm.run_context.fp = 3; @@ -1124,9 +1108,20 @@ mod tests { vm.segments = segments![((1, 0), 2), ((1, 1), 1), ((1, 2), (2, 0))]; let ids_data = ids_data!["a", "b", "range_check_ptr"]; add_segments!(vm, 1); + let identifiers = HashMap::from([ + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), + const_identifier(felt_hex!("4000000000000088000000000000001")), + ), + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), + const_identifier(felt_hex!("2AAAAAAAAAAAAB05555555555555556")), + ), + ]); + let accessible_scopes = vec!["starkware.cairo.common.math.assert_le_felt".to_string()]; //Execute the hint assert_matches!( - run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants), + run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, identifiers, accessible_scopes), Err(HintError::NonLeFelt252(bx)) if *bx == (Felt252::from(2), Felt252::ONE) ); } @@ -1135,24 +1130,26 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_is_assert_le_felt_a_is_not_integer() { let mut vm = vm_with_range_check!(); - let mut constants = HashMap::new(); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_hex!("4000000000000088000000000000001"), - ); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_hex!("2AAAAAAAAAAAAB05555555555555556"), - ); let mut exec_scopes = scope![("excluded", 1)]; //Initialize fp vm.run_context.fp = 3; //Insert ids into memory vm.segments = segments![((1, 0), (1, 0)), ((1, 1), 1), ((1, 2), (2, 0))]; let ids_data = ids_data!["a", "b", "range_check_ptr"]; + let identifiers = HashMap::from([ + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), + const_identifier(felt_hex!("4000000000000088000000000000001")), + ), + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), + const_identifier(felt_hex!("2AAAAAAAAAAAAB05555555555555556")), + ), + ]); + let accessible_scopes = vec!["starkware.cairo.common.math.assert_le_felt".to_string()]; //Execute the hint assert_matches!( - run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants), + run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, identifiers, accessible_scopes), Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "a" ); } @@ -1161,24 +1158,26 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_is_assert_le_felt_b_is_not_integer() { let mut vm = vm_with_range_check!(); - let mut constants = HashMap::new(); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), - felt_hex!("4000000000000088000000000000001"), - ); - constants.insert( - "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), - felt_hex!("2AAAAAAAAAAAAB05555555555555556"), - ); let mut exec_scopes = scope![("excluded", 1)]; //Initialize fp vm.run_context.fp = 3; //Insert ids into memory vm.segments = segments![((1, 0), 1), ((1, 1), (1, 0)), ((1, 2), (2, 0))]; let ids_data = ids_data!["a", "b", "range_check_builtin"]; + let identifiers = HashMap::from([ + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_3_HIGH".to_string(), + const_identifier(felt_hex!("4000000000000088000000000000001")), + ), + ( + "starkware.cairo.common.math.assert_le_felt.PRIME_OVER_2_HIGH".to_string(), + const_identifier(felt_hex!("2AAAAAAAAAAAAB05555555555555556")), + ), + ]); + let accessible_scopes = vec!["starkware.cairo.common.math.assert_le_felt".to_string()]; //Execute the hint assert_matches!( - run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, &constants), + run_hint!(vm, ids_data, hint_code::ASSERT_LE_FELT, &mut exec_scopes, identifiers, accessible_scopes), Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "b" ); } @@ -1858,10 +1857,6 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_assert_250_bit_valid() { let hint_code = hint_code::ASSERT_250_BITS; - let constants = HashMap::from([ - ("UPPER_BOUND".to_string(), Felt252::from(15)), - ("SHIFT".to_string(), Felt252::from(5)), - ]); let mut vm = vm!(); //Initialize fp vm.run_context.fp = 3; @@ -1869,9 +1864,21 @@ mod tests { vm.segments = segments![((1, 0), 1)]; //Create ids let ids_data = ids_data!["value", "high", "low"]; + let identifiers = HashMap::from([ + ("__main__.UPPER_BOUND".to_string(), const_identifier(15)), + ("__main__.SHIFT".to_string(), const_identifier(5)), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( - run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants), + run_hint!( + vm, + ids_data, + hint_code, + &mut exec_scopes_ref!(), + identifiers, + accessible_scopes + ), Ok(()) ); //Hint would return an error if the assertion fails @@ -1883,10 +1890,6 @@ mod tests { #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_assert_250_bit_invalid() { let hint_code = hint_code::ASSERT_250_BITS; - let constants = HashMap::from([ - ("UPPER_BOUND".to_string(), Felt252::from(15)), - ("SHIFT".to_string(), Felt252::from(5)), - ]); let mut vm = vm!(); //Initialize fp vm.run_context.fp = 3; @@ -1901,9 +1904,14 @@ mod tests { )]; //Create ids let ids_data = ids_data!["value", "high", "low"]; + let identifiers = HashMap::from([ + ("__main__.UPPER_BOUND".to_string(), const_identifier(15)), + ("__main__.SHIFT".to_string(), const_identifier(5)), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( - run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), &constants), + run_hint!(vm, ids_data, hint_code, &mut exec_scopes_ref!(), identifiers, accessible_scopes), Err(HintError::ValueOutside250BitRange(bx)) if *bx == pow2_const(251) ); } @@ -1969,6 +1977,11 @@ mod tests { ),]; //Create ids let ids_data = ids_data!["addr", "is_small"]; + let identifiers = HashMap::from([( + "starkware.starknet.common.storage.ADDR_BOUND".to_string(), + const_identifier(addr_bound), + )]); + let accessible_scopes = vec!["starkware.starknet.common.storage".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -1976,10 +1989,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &[(ADDR_BOUND, addr_bound)] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ); @@ -2005,6 +2016,11 @@ mod tests { ),]; //Create ids let ids_data = ids_data!["addr", "is_small"]; + let identifiers = HashMap::from([( + "starkware.starknet.common.storage.ADDR_BOUND".to_string(), + const_identifier(addr_bound), + )]); + let accessible_scopes = vec!["starkware.starknet.common.storage".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -2012,7 +2028,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([(ADDR_BOUND.to_string(), addr_bound)]) + identifiers, + accessible_scopes ), Err(HintError::AssertionFailed(bx)) if bx.as_ref() == "normalize_address() cannot be used with the current constants." @@ -2033,7 +2050,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code), - Err(HintError::MissingConstant(bx)) if *bx == ADDR_BOUND + Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "ADDR_BOUND" ); } @@ -2062,6 +2079,14 @@ mod tests { HintReference::new(-3, 1, true, true, true), ), ]); + let identifiers = HashMap::from([ + ("__main__.MAX_LOW".to_string(), const_identifier(0)), + ( + "__main__.MAX_HIGH".to_string(), + const_identifier(felt_str!("10633823966279327296825105735305134080")), + ), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -2069,13 +2094,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::ZERO), - ( - "MAX_HIGH".to_string(), - felt_str!("10633823966279327296825105735305134080") - ) - ]) + identifiers, + accessible_scopes ), Ok(()) ); @@ -2102,6 +2122,14 @@ mod tests { //Create incomplete ids //Create ids_data & hint_data let ids_data = ids_data!["low"]; + let identifiers = HashMap::from([ + ("__main__.MAX_LOW".to_string(), const_identifier(0)), + ( + "__main__.MAX_HIGH".to_string(), + const_identifier(felt_str!("10633823966279327296825105735305134080")), + ), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -2109,13 +2137,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::ZERO), - ( - "MAX_HIGH".to_string(), - felt_str!("10633823966279327296825105735305134080") - ) - ]) + identifiers, + accessible_scopes ), Err(HintError::UnknownIdentifier(bx)) if bx.as_ref() == "value" ); @@ -2146,6 +2169,14 @@ mod tests { HintReference::new(-3, 1, true, true, true), ), ]); + let identifiers = HashMap::from([ + ("__main__.MAX_LOW".to_string(), const_identifier(0)), + ( + "__main__.MAX_HIGH".to_string(), + const_identifier(felt_str!("10633823966279327296825105735305134080")), + ), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( @@ -2154,13 +2185,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::ZERO), - ( - "MAX_HIGH".to_string(), - felt_str!("10633823966279327296825105735305134080") - ) - ]) + identifiers, + accessible_scopes ), Err(HintError::Memory( MemoryError::InconsistentMemory(bx) @@ -2196,6 +2222,14 @@ mod tests { HintReference::new(-3, 1, true, true, true), ), ]); + let identifiers = HashMap::from([ + ("__main__.MAX_LOW".to_string(), const_identifier(0)), + ( + "__main__.MAX_HIGH".to_string(), + const_identifier(felt_str!("10633823966279327296825105735305134080")), + ), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -2203,13 +2237,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::ZERO), - ( - "MAX_HIGH".to_string(), - felt_str!("10633823966279327296825105735305134080") - ) - ]) + identifiers, + accessible_scopes ), Err(HintError::Memory( MemoryError::InconsistentMemory(bx) @@ -2240,6 +2269,14 @@ mod tests { HintReference::new(-3, 1, true, true, true), ), ]); + let identifiers = HashMap::from([ + ("__main__.MAX_LOW".to_string(), const_identifier(0)), + ( + "__main__.MAX_HIGH".to_string(), + const_identifier(felt_str!("10633823966279327296825105735305134080")), + ), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -2247,13 +2284,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::ZERO), - ( - "MAX_HIGH".to_string(), - felt_str!("10633823966279327296825105735305134080") - ) - ]) + identifiers, + accessible_scopes ), Err(HintError::IdentifierNotInteger(bx)) if bx.as_ref() == "value" ); @@ -2287,7 +2319,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code), - Err(HintError::MissingConstant(x)) if (*x) == "MAX_HIGH" + Err(HintError::UnknownIdentifier(x)) if x.as_ref() == "MAX_HIGH" ); } @@ -2316,6 +2348,11 @@ mod tests { HintReference::new(-3, 1, true, true, true), ), ]); + let identifiers = HashMap::from([ + ("__main__.MAX_LOW".to_string(), const_identifier(-1)), + ("__main__.MAX_HIGH".to_string(), const_identifier(-1)), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -2323,13 +2360,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::from(-1)), - ( - "MAX_HIGH".to_string(), - Felt252::from(-1), - ) - ]) + identifiers, + accessible_scopes ), Err(HintError::AssertionFailed(x)) if &(*x) == "assert ids.MAX_HIGH < 2**128 and ids.MAX_LOW < 2**128" ); @@ -2360,6 +2392,11 @@ mod tests { HintReference::new(-3, 1, true, true, true), ), ]); + let identifiers = HashMap::from([ + ("__main__.MAX_LOW".to_string(), const_identifier(0)), + ("__main__.MAX_HIGH".to_string(), const_identifier(0)), + ]); + let accessible_scopes = vec!["__main__".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -2367,13 +2404,8 @@ mod tests { ids_data, hint_code, exec_scopes_ref!(), - &HashMap::from([ - ("MAX_LOW".to_string(), Felt252::ZERO), - ( - "MAX_HIGH".to_string(), - Felt252::ZERO, - ) - ]) + identifiers, + accessible_scopes ), Err(HintError::AssertionFailed(x)) if &(*x) == "assert PRIME - 1 == ids.MAX_HIGH * 2**128 + ids.MAX_LOW" ); diff --git a/vm/src/hint_processor/builtin_hint_processor/mod_circuit.rs b/vm/src/hint_processor/builtin_hint_processor/mod_circuit.rs index 22fbc57d19..93017dfd61 100644 --- a/vm/src/hint_processor/builtin_hint_processor/mod_circuit.rs +++ b/vm/src/hint_processor/builtin_hint_processor/mod_circuit.rs @@ -1,16 +1,17 @@ -use crate::stdlib::prelude::String; +use crate::serde::deserialize_program::Identifier; +use crate::stdlib::prelude::{Box, String}; +use crate::types::errors::math_errors::MathError; use crate::{ hint_processor::hint_processor_definition::HintReference, serde::deserialize_program::ApTracking, stdlib::collections::HashMap, vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, - Felt252, }; -#[cfg(not(feature = "mod_builtin"))] -use crate::{stdlib::prelude::Box, types::errors::math_errors::MathError}; use num_traits::ToPrimitive; -use super::hint_utils::{get_integer_from_var_name, get_ptr_from_var_name}; +use super::hint_utils::{ + get_constant_from_var_name, get_integer_from_var_name, get_ptr_from_var_name, +}; /* Implements Hint: %{ from starkware.cairo.lang.builtins.modulo.mod_builtin_runner import ModBuiltinRunner @@ -50,21 +51,13 @@ pub fn run_p_mod_circuit_with_large_batch_size( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { - #[cfg(not(feature = "mod_builtin"))] - const LARGE_BATCH_SIZE_PATH: &str = - "starkware.cairo.common.modulo.run_mod_p_circuit_with_large_batch_size.BATCH_SIZE"; - #[cfg(not(feature = "mod_builtin"))] - let batch_size = constants - .get(LARGE_BATCH_SIZE_PATH) - .ok_or_else(|| HintError::MissingConstant(Box::new(LARGE_BATCH_SIZE_PATH)))?; - #[cfg(not(feature = "mod_builtin"))] + let batch_size = get_constant_from_var_name("BATCH_SIZE", identifiers, accessible_scopes)?; let batch_size = batch_size .to_usize() .ok_or_else(|| MathError::Felt252ToUsizeConversion(Box::new(*batch_size)))?; - #[cfg(feature = "mod_builtin")] - let batch_size = 8; // Hardcoded here as we are not importing from the common lib yet run_p_mod_circuit_inner(vm, ids_data, ap_tracking, batch_size) } diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs b/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs index d355ac67c0..c0de264bdf 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/bigint_utils.rs @@ -1,14 +1,16 @@ use core::ops::Shl; +use crate::hint_processor::builtin_hint_processor::hint_utils::get_constant_from_var_name; use crate::hint_processor::builtin_hint_processor::uint_utils::{pack, split}; use crate::math_utils::signed_felt; +use crate::serde::deserialize_program::Identifier; use crate::stdlib::{borrow::Cow, boxed::Box, collections::HashMap, prelude::*}; use crate::Felt252; use crate::{ hint_processor::{ builtin_hint_processor::{ hint_utils::{get_relocatable_from_var_name, insert_value_from_var_name}, - secp::secp_utils::{bigint3_split, BASE_86}, + secp::secp_utils::bigint3_split, }, hint_processor_definition::HintReference, }, @@ -151,16 +153,15 @@ pub fn bigint_to_uint256( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let x_struct = get_relocatable_from_var_name("x", vm, ids_data, ap_tracking)?; let d0 = vm.get_integer(x_struct)?; let d1 = vm.get_integer((x_struct + 1_i32)?)?; let d0 = d0.as_ref(); let d1 = d1.as_ref(); - let base_86 = constants - .get(BASE_86) - .ok_or_else(|| HintError::MissingConstant(Box::new(BASE_86)))?; + let base_86 = get_constant_from_var_name("BASE", identifiers, accessible_scopes)?; let mask = pow2_const_nz(128); let low = (d0 + (d1 * base_86)).mod_floor(mask); insert_value_from_var_name("low", low, vm, ids_data, ap_tracking) @@ -227,16 +228,19 @@ mod tests { run_context!(vm, 0, 6, 6); //Create hint_data let ids_data = non_continuous_ids_data![("res", 5)]; + let identifiers = HashMap::from([( + "starkware.cairo.common.cairo_secp.constants.BASE".to_string(), + const_identifier(crate::math_utils::pow2_const(86)), + )]); + let accessible_scopes = vec!["starkware.cairo.common.cairo_secp.constants".to_string()]; assert_matches!( run_hint!( vm, ids_data, hint_code, &mut exec_scopes, - &[(BASE_86, crate::math_utils::pow2_const(86))] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ); diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs b/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs index 92ab043479..6725d3b5a2 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/cairo0_hints.rs @@ -1,8 +1,10 @@ -use crate::stdlib::{ - collections::HashMap, - ops::Deref, - ops::{Add, Mul, Rem}, - prelude::*, +use crate::{ + serde::deserialize_program::Identifier, + stdlib::{ + collections::HashMap, + ops::{Add, Deref, Mul, Rem}, + prelude::*, + }, }; use crate::define_hint_string_map; @@ -126,7 +128,8 @@ pub fn reduce_value( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { let x = Uint384::from_var_name("x", vm, ids_data, ap_tracking)?.pack86(); exec_scopes.insert_value("value", x.mod_floor(&SECP256R1_P)); @@ -138,7 +141,8 @@ pub fn reduce_x( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { let x = Uint384::from_var_name("x", vm, ids_data, ap_tracking)?.pack86(); exec_scopes.insert_value("x", x.mod_floor(&SECP256R1_P)); @@ -150,7 +154,8 @@ pub fn compute_q_mod_prime( _exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { let val = Uint384::from_var_name("val", vm, ids_data, ap_tracking)?.pack86(); let (q, r) = val.div_mod_floor(&SECP256R1_P); @@ -166,19 +171,13 @@ pub fn compute_ids_high_low( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { exec_scopes.insert_value::("SECP256R1_P", SECP256R1_P.clone()); - const UPPER_BOUND: &str = "starkware.cairo.common.secp256r1.field.assert_165_bit.UPPER_BOUND"; - const SHIFT: &str = "starkware.cairo.common.secp256r1.field.assert_165_bit.SHIFT"; - - let upper_bound = constants - .get(UPPER_BOUND) - .map_or_else(|| get_constant_from_var_name("UPPER_BOUND", constants), Ok)?; - let shift = constants - .get(SHIFT) - .map_or_else(|| get_constant_from_var_name("SHIFT", constants), Ok)?; + let upper_bound = get_constant_from_var_name("UPPER_BOUND", identifiers, accessible_scopes)?; + let shift = get_constant_from_var_name("SHIFT", identifiers, accessible_scopes)?; let value = Felt252::from(&signed_felt(get_integer_from_var_name( "value", vm, @@ -200,7 +199,8 @@ pub fn r1_get_point_from_x( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], pack_prime: &BigUint, ) -> Result<(), HintError> { exec_scopes.insert_value::("SECP256R1_P", SECP256R1_P.clone()); @@ -261,7 +261,8 @@ pub fn is_on_curve_2( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { let y: BigInt = exec_scopes.get("y")?; let y_square_int: BigInt = exec_scopes.get("y_square_int")?; @@ -283,7 +284,8 @@ pub fn secp_double_assign_new_x( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], pack_prime: &BigUint, ) -> Result<(), HintError> { exec_scopes.insert_value::("SECP256R1_P", SECP256R1_P.clone()); @@ -313,7 +315,8 @@ pub fn generate_nibbles( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { let num = Uint256::from_var_name("scalar", vm, ids_data, ap_tracking)?.pack(); @@ -341,7 +344,8 @@ pub fn fast_secp_add_assign_new_y( exec_scopes: &mut ExecutionScopes, _ids_data: &HashMap, _ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { //Get variables from vm scope let (slope, x, new_x, y, secp_p) = ( @@ -363,7 +367,8 @@ pub fn write_nibbles_to_mem( exec_scopes: &mut ExecutionScopes, _ids_data: &HashMap, _ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { let nibbles: &mut Vec = exec_scopes.get_mut_list_ref("nibbles")?; let nibble = nibbles.pop().ok_or(HintError::EmptyNibbles)?; @@ -377,7 +382,8 @@ pub fn compute_value_div_mod( exec_scopes: &mut ExecutionScopes, _ids_data: &HashMap, _ap_tracking: &ApTracking, - _constants: &HashMap, + _identifiers: &HashMap, + _accessible_scopes: &[String], ) -> Result<(), HintError> { //Get variables from vm scope let x = exec_scopes.get_ref::("x")?; @@ -423,6 +429,7 @@ mod tests { &ids_data, &ap_tracking, &Default::default(), + &[], ) .expect("is_on_curve2() failed"); @@ -451,6 +458,7 @@ mod tests { &ids_data, &ap_tracking, &Default::default(), + &[], ) .expect("compute_q_mod_prime() failed"); @@ -503,19 +511,21 @@ mod tests { let mut exec_scopes = ExecutionScopes::new(); - let constants = HashMap::from([ + let identifiers = HashMap::from([ ( - "UPPER_BOUND".to_string(), - Felt252::from(18446744069414584321_u128), + "__main__.UPPER_BOUND".to_string(), + const_identifier(18446744069414584321_u128), ), - ("SHIFT".to_string(), Felt252::from(12)), + ("__main__.SHIFT".to_string(), const_identifier(12)), ]); + let accessible_scopes = vec!["__main__".to_string()]; compute_ids_high_low( &mut vm, &mut exec_scopes, &ids_data, &ap_tracking, - &constants, + &identifiers, + &accessible_scopes, ) .expect("compute_ids_high_low() failed"); @@ -561,6 +571,7 @@ mod tests { &ids_data, &ap_tracking, &constants, + &[], SECP256R1_P.magnitude(), ) .expect("calculate_value() failed"); @@ -634,6 +645,7 @@ mod tests { &ids_data, &ap_tracking, &Default::default(), + &[], ) .expect("reduce_value() failed"); @@ -690,6 +702,7 @@ mod tests { &ids_data, &ap_tracking, &Default::default(), + &[], ) .expect("x() failed"); diff --git a/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs b/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs index b495ab073f..1bdeca1ab1 100644 --- a/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs +++ b/vm/src/hint_processor/builtin_hint_processor/secp/signature.rs @@ -1,8 +1,9 @@ -use crate::Felt252; +use crate::hint_processor::builtin_hint_processor::hint_utils::get_constant_from_var_name; +use crate::serde::deserialize_program::Identifier; use crate::{ any_box, hint_processor::{ - builtin_hint_processor::{hint_utils::get_integer_from_var_name, secp::secp_utils::BETA}, + builtin_hint_processor::hint_utils::get_integer_from_var_name, hint_processor_definition::HintReference, }, math_utils::{div_mod, safe_div_bigint}, @@ -106,13 +107,11 @@ pub fn get_point_from_x( exec_scopes: &mut ExecutionScopes, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { exec_scopes.insert_value("SECP_P", SECP_P.clone()); - let beta = constants - .get(BETA) - .ok_or_else(|| HintError::MissingConstant(Box::new(BETA)))? - .to_bigint(); + let beta = get_constant_from_var_name("BETA", identifiers, accessible_scopes)?.to_bigint(); let x_cube_int = Uint384::from_var_name("x_cube", vm, ids_data, ap_tracking)? .pack86() @@ -252,16 +251,19 @@ mod tests { ]; vm.run_context.fp = 1; let ids_data = non_continuous_ids_data![("v", -1), ("x_cube", 0)]; + let identifiers = HashMap::from([( + "starkware.cairo.common.cairo_secp.constants.BETA".to_string(), + const_identifier(7), + )]); + let accessible_scopes = vec!["starkware.cairo.common.cairo_secp.constants".to_string()]; assert_matches!( run_hint!( vm, ids_data, hint_code, exec_scopes_ref!(), - &[(BETA, Felt252::from(7)),] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ) @@ -282,16 +284,19 @@ mod tests { vm.run_context.fp = 2; let ids_data = ids_data!["v", "x_cube"]; + let identifiers = HashMap::from([( + "starkware.cairo.common.cairo_secp.constants.BETA".to_string(), + const_identifier(7), + )]); + let accessible_scopes = vec!["starkware.cairo.common.cairo_secp.constants".to_string()]; assert_matches!( run_hint!( vm, ids_data, hint_code, &mut exec_scopes, - &[(BETA, Felt252::from(7)),] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ); diff --git a/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs b/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs index a7e77bd42c..69beefcab8 100644 --- a/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs +++ b/vm/src/hint_processor/builtin_hint_processor/sha256_utils.rs @@ -1,3 +1,4 @@ +use crate::serde::deserialize_program::Identifier; use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; use crate::Felt252; @@ -53,25 +54,31 @@ fn sha256_main( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], iv: &mut [u32; 8], ) -> Result<(), HintError> { let input_ptr = get_ptr_from_var_name("sha256_start", vm, ids_data, ap_tracking)?; - // The original code gets it from `ids` in both cases, and this makes it easier - // to implement the arbitrary length one - let input_chunk_size_felts = - get_constant_from_var_name("SHA256_INPUT_CHUNK_SIZE_FELTS", constants)? - .to_usize() - .unwrap_or(100); // Hack: enough to fail the assertion - - if input_chunk_size_felts >= 100 { - return Err(HintError::AssertionFailed( - "assert 0 <= _sha256_input_chunk_size_felts < 100" - .to_string() - .into_boxed_str(), - )); - } + // The code gets the value from `ids.SHA256_INPUT_CHUNK_SIZE_FELTS` in both + // constant and arbitrary input length cases. + let input_chunk_size_felts = get_constant_from_var_name( + "SHA256_INPUT_CHUNK_SIZE_FELTS", + identifiers, + accessible_scopes, + )?; + + // The input chunk size must be less than 100. + let input_chunk_size_felts = match input_chunk_size_felts.to_usize() { + Some(size) if size < 100 => size, + _ => { + return Err(HintError::AssertionFailed( + "assert 0 <= _sha256_input_chunk_size_felts < 100" + .to_string() + .into_boxed_str(), + )); + } + }; let mut message: Vec = Vec::with_capacity(4 * input_chunk_size_felts); @@ -113,10 +120,18 @@ pub fn sha256_main_constant_input_length( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let mut iv = IV; - sha256_main(vm, ids_data, ap_tracking, constants, &mut iv) + sha256_main( + vm, + ids_data, + ap_tracking, + identifiers, + accessible_scopes, + &mut iv, + ) } /* Implements hint: @@ -136,11 +151,13 @@ pub fn sha256_main_arbitrary_input_length( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let iv_ptr = get_ptr_from_var_name("state", vm, ids_data, ap_tracking)?; - let state_size_felt = get_constant_from_var_name("SHA256_STATE_SIZE_FELTS", constants)?; + let state_size_felt = + get_constant_from_var_name("SHA256_STATE_SIZE_FELTS", identifiers, accessible_scopes)?; let state_size = match state_size_felt.to_usize() { Some(size) if size == SHA256_STATE_SIZE_FELTS => size, @@ -171,7 +188,14 @@ pub fn sha256_main_arbitrary_input_length( .try_into() .expect("size is constant"); - sha256_main(vm, ids_data, ap_tracking, constants, &mut iv) + sha256_main( + vm, + ids_data, + ap_tracking, + identifiers, + accessible_scopes, + &mut iv, + ) } pub fn sha256_finalize( @@ -287,12 +311,20 @@ mod tests { ]; vm.run_context.fp = 2; let ids_data = ids_data!["sha256_start", "output"]; - let constants = HashMap::from([( - "SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), - Felt252::from(SHA256_INPUT_CHUNK_SIZE_FELTS), + let identifiers = HashMap::from([( + "__main__.SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), + const_identifier(SHA256_INPUT_CHUNK_SIZE_FELTS), )]); + let accessible_scopes = vec!["__main__".to_string()]; assert_matches!( - run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), &constants), + run_hint!( + &mut vm, + ids_data, + hint_code, + exec_scopes_ref!(), + identifiers, + accessible_scopes + ), Ok(()) ); @@ -347,18 +379,26 @@ mod tests { ]; vm.run_context.fp = 3; let ids_data = ids_data!["sha256_start", "output", "state"]; - let constants = HashMap::from([ + let identifiers = HashMap::from([ ( - "SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), - Felt252::from(SHA256_INPUT_CHUNK_SIZE_FELTS), + "__main__.SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), + const_identifier(SHA256_INPUT_CHUNK_SIZE_FELTS), ), ( - "SHA256_STATE_SIZE_FELTS".to_string(), - Felt252::from(SHA256_STATE_SIZE_FELTS), + "__main__.SHA256_STATE_SIZE_FELTS".to_string(), + const_identifier(SHA256_STATE_SIZE_FELTS), ), ]); + let accessible_scopes = vec!["__main__".to_string()]; assert_matches!( - run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), &constants), + run_hint!( + &mut vm, + ids_data, + hint_code, + exec_scopes_ref!(), + identifiers, + accessible_scopes + ), Ok(()) ); check_memory![ @@ -396,18 +436,19 @@ mod tests { ]; vm.run_context.fp = 3; let ids_data = ids_data!["sha256_start", "output", "state"]; - let constants = HashMap::from([ + let identifiers = HashMap::from([ ( - "SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), - Felt252::from(100), + "__main__.SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), + const_identifier(100), ), ( - "SHA256_STATE_SIZE_FELTS".to_string(), - Felt252::from(SHA256_STATE_SIZE_FELTS), + "__main__.SHA256_STATE_SIZE_FELTS".to_string(), + const_identifier(SHA256_STATE_SIZE_FELTS), ), ]); + let accessible_scopes = vec!["__main__".to_string()]; assert_matches!( - run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), &constants), + run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), identifiers, accessible_scopes), Err(HintError::AssertionFailed(bx)) if bx.as_ref() == "assert 0 <= _sha256_input_chunk_size_felts < 100" ); } @@ -433,15 +474,19 @@ mod tests { ]; vm.run_context.fp = 3; let ids_data = ids_data!["sha256_start", "output", "state"]; - let constants = HashMap::from([ + let identifiers = HashMap::from([ + ( + "__main__.SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), + const_identifier(SHA256_INPUT_CHUNK_SIZE_FELTS), + ), ( - "SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), - Felt252::from(SHA256_INPUT_CHUNK_SIZE_FELTS), + "__main__.SHA256_STATE_SIZE_FELTS".to_string(), + const_identifier(100), ), - ("SHA256_STATE_SIZE_FELTS".to_string(), Felt252::from(100)), ]); + let accessible_scopes = vec!["__main__".to_string()]; assert_matches!( - run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), &constants), + run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), identifiers, accessible_scopes), Err(HintError::AssertionFailed(bx)) if bx.as_ref() == "assert 0 <= _sha256_state_size_felts < 100" ); } @@ -468,16 +513,20 @@ mod tests { ]; vm.run_context.fp = 3; let ids_data = ids_data!["sha256_start", "output", "state"]; - let constants = HashMap::from([ + let identifiers = HashMap::from([ + ( + "__main__.SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), + const_identifier(SHA256_INPUT_CHUNK_SIZE_FELTS), + ), ( - "SHA256_INPUT_CHUNK_SIZE_FELTS".to_string(), - Felt252::from(SHA256_INPUT_CHUNK_SIZE_FELTS), + "__main__.SHA256_STATE_SIZE_FELTS".to_string(), + const_identifier(state_size), ), - ("SHA256_STATE_SIZE_FELTS".to_string(), state_size), ]); + let accessible_scopes = vec!["__main__".to_string()]; let expected_size = Felt252::from(SHA256_STATE_SIZE_FELTS); assert_matches!( - run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), &constants), + run_hint!(&mut vm, ids_data, hint_code, exec_scopes_ref!(), identifiers, accessible_scopes), Err(HintError::InvalidValue(bx)) if *bx == ("SHA256_STATE_SIZE_FELTS", state_size, expected_size) ); diff --git a/vm/src/hint_processor/builtin_hint_processor/uint384.rs b/vm/src/hint_processor/builtin_hint_processor/uint384.rs index a973fb9d3d..ebfc9e777d 100644 --- a/vm/src/hint_processor/builtin_hint_processor/uint384.rs +++ b/vm/src/hint_processor/builtin_hint_processor/uint384.rs @@ -1,3 +1,4 @@ +use crate::serde::deserialize_program::Identifier; use crate::Felt252; use num_bigint::BigUint; use num_integer::Integer; @@ -102,12 +103,13 @@ pub fn add_no_uint384_check( vm: &mut VirtualMachine, ids_data: &HashMap, ap_tracking: &ApTracking, - constants: &HashMap, + identifiers: &HashMap, + accessible_scopes: &[String], ) -> Result<(), HintError> { let a = Uint384::from_var_name("a", vm, ids_data, ap_tracking)?; let b = Uint384::from_var_name("b", vm, ids_data, ap_tracking)?; // This hint is not from the cairo commonlib, and its lib can be found under different paths, so we cant rely on a full path name - let shift = get_constant_from_var_name("SHIFT", constants)?.to_biguint(); + let shift = get_constant_from_var_name("SHIFT", identifiers, accessible_scopes)?.to_biguint(); let sum_d0 = (a.limbs[0].as_ref().to_biguint()) + (b.limbs[0].as_ref().to_biguint()); let carry_d0 = BigUint::from((sum_d0 >= shift) as usize); @@ -488,6 +490,11 @@ mod tests { ((1, 4), 17), ((1, 5), 8) ]; + let identifiers = HashMap::from([( + "path.path.path.SHIFT".to_string(), + const_identifier(crate::math_utils::pow2_const(128)), + )]); + let accessible_scopes = vec!["path.path.path".to_string()]; //Execute the hint assert_matches!( run_hint!( @@ -495,10 +502,8 @@ mod tests { ids_data, hint_code::ADD_NO_UINT384_CHECK, &mut exec_scopes_ref!(), - &[("path.path.path.SHIFT", crate::math_utils::pow2_const(128))] - .into_iter() - .map(|(k, v)| (k.to_string(), v)) - .collect() + identifiers, + accessible_scopes ), Ok(()) ); @@ -542,7 +547,7 @@ mod tests { //Execute the hint assert_matches!( run_hint!(vm, ids_data, hint_code::ADD_NO_UINT384_CHECK), - Err(HintError::MissingConstant(bx)) if *bx == "SHIFT" + Err(HintError::UnknownIdentifier(x)) if x.as_ref() == "SHIFT" ); } diff --git a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs index 426df07159..d3048fdfd5 100644 --- a/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs +++ b/vm/src/hint_processor/cairo_1_hint_processor/hint_processor.rs @@ -9,6 +9,7 @@ use super::hint_processor_utils::*; use crate::any_box; use crate::hint_processor::cairo_1_hint_processor::dict_manager::DictSquashExecScope; use crate::hint_processor::hint_processor_definition::HintReference; +use crate::serde::deserialize_program::Identifier; use crate::stdlib::rc::Rc; use crate::stdlib::{boxed::Box, collections::HashMap, prelude::*}; use crate::types::relocatable::{MaybeRelocatable, Relocatable}; @@ -1265,7 +1266,8 @@ impl HintProcessorLogic for Cairo1HintProcessor { //List of all references (key corresponds to element of the previous dictionary) _references: &[HintReference], // Identifiers stored in the hint's program. - _constants: Rc>, + _constants: Rc>, + _accessible_scopes: &[String], ) -> Result, VirtualMachineError> { let data = hint_code.parse().ok().and_then(|x: usize| self.hints.get(&x).cloned()) .ok_or_else(|| VirtualMachineError::CompileHintFail( diff --git a/vm/src/hint_processor/hint_processor_definition.rs b/vm/src/hint_processor/hint_processor_definition.rs index 60d57772ee..b1a05e9910 100644 --- a/vm/src/hint_processor/hint_processor_definition.rs +++ b/vm/src/hint_processor/hint_processor_definition.rs @@ -1,9 +1,9 @@ use crate::stdlib::{any::Any, boxed::Box, collections::HashMap, prelude::*, rc::Rc}; use crate::any_box; -use crate::serde::deserialize_program::ApTracking; use crate::serde::deserialize_program::OffsetValue; use crate::serde::deserialize_program::Reference; +use crate::serde::deserialize_program::{ApTracking, Identifier}; use crate::types::exec_scope::ExecutionScopes; use crate::types::instruction::Register; use crate::types::relocatable::Relocatable; @@ -13,7 +13,6 @@ use crate::vm::runners::cairo_runner::ResourceTracker; use crate::vm::vm_core::VirtualMachine; use super::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; -use crate::Felt252; #[cfg(feature = "test_utils")] use arbitrary::Arbitrary; @@ -42,13 +41,16 @@ pub trait HintProcessorLogic { //List of all references (key corresponds to element of the previous dictionary) references: &[HintReference], // Identifiers stored in the hint's program. - constants: Rc>, + identifiers: Rc>, + // List of accessible scopes in the hint + accessible_scopes: &[String], ) -> Result, VirtualMachineError> { Ok(any_box!(HintProcessorData { code: hint_code.to_string(), ap_tracking: ap_tracking_data.clone(), ids_data: get_ids_data(reference_ids, references)?, - constants, + identifiers, + accessible_scopes: accessible_scopes.to_vec(), })) } diff --git a/vm/src/tests/cairo_run_test.rs b/vm/src/tests/cairo_run_test.rs index 03758cc285..391f854dbc 100644 --- a/vm/src/tests/cairo_run_test.rs +++ b/vm/src/tests/cairo_run_test.rs @@ -1370,3 +1370,10 @@ fn cairo_run_data_availability_reduced_mul() { include_bytes!("../../../cairo_programs/cairo-0-kzg-da-hints/reduced_mul.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn constant_collision() { + let program_data = include_bytes!("../../../cairo_programs/constant_collision.json"); + run_program_simple(program_data.as_slice()); +} diff --git a/vm/src/tests/run_deprecated_contract_class_simplified.rs b/vm/src/tests/run_deprecated_contract_class_simplified.rs index 13f6869a1c..d017eba7f3 100644 --- a/vm/src/tests/run_deprecated_contract_class_simplified.rs +++ b/vm/src/tests/run_deprecated_contract_class_simplified.rs @@ -290,6 +290,10 @@ pub fn vm_load_program( let hint_ap_tracking_data = ApTracking::default(); let reference_ids = HashMap::default(); let references = vec![]; + let accessible_scopes = vec![ + String::from("__main__"), + String::from("__main__.get_number"), + ]; // Compile the hint let compiled_hint = hint_processor.compile_hint( hint_code, @@ -297,6 +301,7 @@ pub fn vm_load_program( &reference_ids, &references, Default::default(), + &accessible_scopes, )?; // Create the hint extension // As the hint from the compiled constract has offset 0, the hint pc will be equal to the loaded contract's program base: diff --git a/vm/src/utils.rs b/vm/src/utils.rs index 6824252fe2..c9fc4000a9 100644 --- a/vm/src/utils.rs +++ b/vm/src/utils.rs @@ -52,9 +52,12 @@ pub fn from_relocatable_to_indexes(relocatable: Relocatable) -> (usize, usize) { #[cfg(test)] #[macro_use] pub mod test_utils { + use crate::serde::deserialize_program::Identifier; + use crate::stdlib::string::String; use crate::types::exec_scope::ExecutionScopes; use crate::types::relocatable::MaybeRelocatable; use crate::vm::trace::trace_entry::TraceEntry; + use crate::Felt252; #[macro_export] macro_rules! felt_hex { @@ -472,11 +475,36 @@ pub mod test_utils { } pub(crate) use exec_scopes_ref; + pub fn const_identifier(value: impl Into) -> Identifier { + Identifier { + pc: None, + type_: Some(String::from("const")), + value: Some(value.into()), + full_name: None, + members: None, + cairo_type: None, + size: None, + destination: None, + } + } + pub fn alias_identifier(destination: impl Into) -> Identifier { + Identifier { + pc: None, + type_: Some(String::from("alias")), + value: None, + full_name: None, + members: None, + cairo_type: None, + size: None, + destination: Some(destination.into()), + } + } + macro_rules! run_hint { - ($vm:expr, $ids_data:expr, $hint_code:expr, $exec_scopes:expr, $constants:expr) => {{ + ($vm:expr, $ids_data:expr, $hint_code:expr, $exec_scopes:expr, $identifiers:expr, $accessible_scopes:expr) => {{ let mut hint_data = HintProcessorData::new_default($hint_code.to_string(), $ids_data); - let constants: &HashMap = $constants; - hint_data.constants = crate::stdlib::rc::Rc::new(constants.clone()); + hint_data.identifiers = crate::stdlib::rc::Rc::new($identifiers); + hint_data.accessible_scopes = $accessible_scopes; let mut hint_processor = BuiltinHintProcessor::new_empty(); hint_processor.execute_hint(&mut $vm, $exec_scopes, &any_box!(hint_data)) }}; diff --git a/vm/src/vm/errors/hint_errors.rs b/vm/src/vm/errors/hint_errors.rs index 8d5f61fcb5..c11f7a1d0b 100644 --- a/vm/src/vm/errors/hint_errors.rs +++ b/vm/src/vm/errors/hint_errors.rs @@ -42,10 +42,12 @@ pub enum HintError { UnknownIdentifierInternal, #[error("Wrong identifier type")] WrongIdentifierTypeInternal, + #[error("Encountered cyclic aliasing")] + CyclicAliasing, #[error("Hint Error: {0}")] CustomHint(Box), #[error("Missing constant: {0}")] - MissingConstant(Box<&'static str>), + MissingConstant(Box), #[error("Fail to get constants for hint execution")] FailedToGetConstant, #[error("Arc too big, {} must be <= {} and {} <= {}", (*.0).0, (*.0).1, (*.0).2, (*.0).3)] diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 2a0ecfe964..f7dac14bd6 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -644,7 +644,7 @@ impl CairoRunner { references: &[HintReference], hint_executor: &mut dyn HintProcessor, ) -> Result>, VirtualMachineError> { - let constants = Rc::new(self.program.constants.clone()); + let identifiers = Rc::new(self.program.shared_program_data.identifiers.clone()); self.program .shared_program_data @@ -657,7 +657,8 @@ impl CairoRunner { &hint.flow_tracking_data.ap_tracking, &hint.flow_tracking_data.reference_ids, references, - constants.clone(), + identifiers.clone(), + &hint.accessible_scopes, ) .map_err(|_| VirtualMachineError::CompileHintFail(hint.code.clone().into())) })