From 5f0cd036f242cd98da1cdf4019d3ed6c1b04f39c Mon Sep 17 00:00:00 2001 From: Pedro Fontana Date: Mon, 17 Apr 2023 11:24:02 -0300 Subject: [PATCH] refactor: make hints code public (#988) * refactor: make hints code public * Update Changelog * Update Changelog --------- Co-authored-by: Pedro Fontana --- CHANGELOG.md | 2 + .../builtin_hint_processor/hint_code.rs | 246 +++++++++--------- 2 files changed, 120 insertions(+), 128 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79efe58bfb..0a0c85a88c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,6 +95,8 @@ segments.write_arg(ids.keccak_ptr, output_values) ``` +* Make hints code `src/hint_processor/builtin_hint_processor/hint_code.rs` public [#988](https://github.com/lambdaclass/cairo-rs/pull/988) + * Implement hints on uint384 lib (Part 1) [#960](https://github.com/lambdaclass/cairo-rs/pull/960) `BuiltinHintProcessor` now supports the following hints: diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 8bf667122e..6f4d3b5d53 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -1,36 +1,35 @@ -pub(crate) const ADD_SEGMENT: &str = "memory[ap] = segments.add()"; +pub const ADD_SEGMENT: &str = "memory[ap] = segments.add()"; -pub(crate) const VM_ENTER_SCOPE: &str = "vm_enter_scope()"; -pub(crate) const VM_EXIT_SCOPE: &str = "vm_exit_scope()"; +pub const VM_ENTER_SCOPE: &str = "vm_enter_scope()"; +pub const VM_EXIT_SCOPE: &str = "vm_exit_scope()"; -pub(crate) const MEMCPY_ENTER_SCOPE: &str = "vm_enter_scope({'n': ids.len})"; -pub(crate) const MEMCPY_CONTINUE_COPYING: &str = r#"n -= 1 +pub const MEMCPY_ENTER_SCOPE: &str = "vm_enter_scope({'n': ids.len})"; +pub const MEMCPY_CONTINUE_COPYING: &str = r#"n -= 1 ids.continue_copying = 1 if n > 0 else 0"#; -pub(crate) const MEMSET_ENTER_SCOPE: &str = "vm_enter_scope({'n': ids.n})"; -pub(crate) const MEMSET_CONTINUE_LOOP: &str = r#"n -= 1 +pub const MEMSET_ENTER_SCOPE: &str = "vm_enter_scope({'n': ids.n})"; +pub const MEMSET_CONTINUE_LOOP: &str = r#"n -= 1 ids.continue_loop = 1 if n > 0 else 0"#; -pub(crate) const POW: &str = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1"; +pub const POW: &str = "ids.locs.bit = (ids.prev_locs.exp % PRIME) & 1"; -pub(crate) const IS_NN: &str = - "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1"; -pub(crate) const IS_NN_OUT_OF_RANGE: &str = +pub const IS_NN: &str = "memory[ap] = 0 if 0 <= (ids.a % PRIME) < range_check_builtin.bound else 1"; +pub const IS_NN_OUT_OF_RANGE: &str = "memory[ap] = 0 if 0 <= ((-ids.a - 1) % PRIME) < range_check_builtin.bound else 1"; -pub(crate) const IS_LE_FELT: &str = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1"; -pub(crate) const IS_POSITIVE: &str = r#"from starkware.cairo.common.math_utils import is_positive +pub const IS_LE_FELT: &str = "memory[ap] = 0 if (ids.a % PRIME) <= (ids.b % PRIME) else 1"; +pub const IS_POSITIVE: &str = r#"from starkware.cairo.common.math_utils import is_positive ids.is_positive = 1 if is_positive( value=ids.value, prime=PRIME, rc_bound=range_check_builtin.bound) else 0"#; -pub(crate) const ASSERT_NN: &str = r#"from starkware.cairo.common.math_utils import assert_integer +pub const ASSERT_NN: &str = r#"from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.a) assert 0 <= ids.a % PRIME < range_check_builtin.bound, f'a = {ids.a} is out of range.'"#; -pub(crate) const ASSERT_NOT_ZERO: &str = r#"from starkware.cairo.common.math_utils import assert_integer +pub const ASSERT_NOT_ZERO: &str = r#"from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.value) assert ids.value % PRIME != 0, f'assert_not_zero failed: {ids.value} = 0.'"#; -pub(crate) const ASSERT_NOT_EQUAL: &str = r#"from starkware.cairo.lang.vm.relocatable import RelocatableValue +pub const ASSERT_NOT_EQUAL: &str = r#"from starkware.cairo.lang.vm.relocatable import RelocatableValue both_ints = isinstance(ids.a, int) and isinstance(ids.b, int) both_relocatable = ( isinstance(ids.a, RelocatableValue) and isinstance(ids.b, RelocatableValue) and @@ -39,7 +38,7 @@ assert both_ints or both_relocatable, \ f'assert_not_equal failed: non-comparable values: {ids.a}, {ids.b}.' assert (ids.a - ids.b) % PRIME != 0, f'assert_not_equal failed: {ids.a} = {ids.b}.'"#; -pub(crate) const ASSERT_LE_FELT: &str = r#"import itertools +pub const ASSERT_LE_FELT: &str = r#"import itertools from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.a) @@ -59,20 +58,20 @@ memory[ids.range_check_ptr + 1], memory[ids.range_check_ptr + 0] = ( memory[ids.range_check_ptr + 3], memory[ids.range_check_ptr + 2] = ( divmod(lengths_and_indices[1][0], ids.PRIME_OVER_2_HIGH))"#; -pub(crate) const ASSERT_LE_FELT_EXCLUDED_0: &str = "memory[ap] = 1 if excluded != 0 else 0"; -pub(crate) const ASSERT_LE_FELT_EXCLUDED_1: &str = "memory[ap] = 1 if excluded != 1 else 0"; -pub(crate) const ASSERT_LE_FELT_EXCLUDED_2: &str = "assert excluded == 2"; +pub const ASSERT_LE_FELT_EXCLUDED_0: &str = "memory[ap] = 1 if excluded != 0 else 0"; +pub const ASSERT_LE_FELT_EXCLUDED_1: &str = "memory[ap] = 1 if excluded != 1 else 0"; +pub const ASSERT_LE_FELT_EXCLUDED_2: &str = "assert excluded == 2"; -pub(crate) const ASSERT_LT_FELT: &str = r#"from starkware.cairo.common.math_utils import assert_integer +pub const ASSERT_LT_FELT: &str = r#"from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.a) assert_integer(ids.b) assert (ids.a % PRIME) < (ids.b % PRIME), \ f'a = {ids.a % PRIME} is not less than b = {ids.b % PRIME}.'"#; -pub(crate) const SPLIT_INT_ASSERT_RANGE: &str = +pub const SPLIT_INT_ASSERT_RANGE: &str = "assert ids.value == 0, 'split_int(): value is out of range.'"; -pub(crate) const ASSERT_250_BITS: &str = r#"from starkware.cairo.common.math_utils import as_int +pub const ASSERT_250_BITS: &str = r#"from starkware.cairo.common.math_utils import as_int # Correctness check. value = as_int(ids.value, PRIME) % PRIME @@ -81,32 +80,32 @@ assert value < ids.UPPER_BOUND, f'{value} is outside of the range [0, 2**250).' # Calculation for the assertion. ids.high, ids.low = divmod(ids.value, ids.SHIFT)"#; -pub(crate) const SPLIT_INT: &str = r#"memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base +pub const SPLIT_INT: &str = r#"memory[ids.output] = res = (int(ids.value) % PRIME) % ids.base assert res < ids.bound, f'split_int(): Limb {res} is out of range.'"#; -pub(crate) const SPLIT_64: &str = r#"ids.low = ids.a & ((1<<64) - 1) +pub const SPLIT_64: &str = r#"ids.low = ids.a & ((1<<64) - 1) ids.high = ids.a >> 64"#; -pub(crate) const SPLIT_FELT: &str = r#"from starkware.cairo.common.math_utils import assert_integer +pub const SPLIT_FELT: &str = r#"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"#; -pub(crate) const SQRT: &str = r#"from starkware.python.math_utils import isqrt +pub const SQRT: &str = r#"from starkware.python.math_utils import isqrt value = ids.value % PRIME assert value < 2 ** 250, f"value={value} is outside of the range [0, 2**250)." assert 2 ** 250 < PRIME ids.root = isqrt(value)"#; -pub(crate) const UNSIGNED_DIV_REM: &str = r#"from starkware.cairo.common.math_utils import assert_integer +pub const UNSIGNED_DIV_REM: &str = r#"from starkware.cairo.common.math_utils import assert_integer assert_integer(ids.div) assert 0 < ids.div <= PRIME // range_check_builtin.bound, \ f'div={hex(ids.div)} is out of the valid range.' ids.q, ids.r = divmod(ids.value, ids.div)"#; -pub(crate) const SIGNED_DIV_REM: &str = r#"from starkware.cairo.common.math_utils import as_int, assert_integer +pub const SIGNED_DIV_REM: &str = r#"from starkware.cairo.common.math_utils import as_int, assert_integer assert_integer(ids.div) assert 0 < ids.div <= PRIME // range_check_builtin.bound, \ @@ -124,7 +123,7 @@ assert -ids.bound <= q < ids.bound, \ ids.biased_q = q + ids.bound"#; -pub(crate) const IS_QUAD_RESIDUE: &str = r#"from starkware.crypto.signature.signature import FIELD_PRIME +pub const IS_QUAD_RESIDUE: &str = r#"from starkware.crypto.signature.signature import FIELD_PRIME from starkware.python.math_utils import div_mod, is_quad_residue, sqrt x = ids.x @@ -133,7 +132,7 @@ if is_quad_residue(x, FIELD_PRIME): else: ids.y = sqrt(div_mod(x, 3, FIELD_PRIME), FIELD_PRIME)"#; -pub(crate) const FIND_ELEMENT: &str = r#"array_ptr = ids.array_ptr +pub const FIND_ELEMENT: &str = r#"array_ptr = ids.array_ptr elm_size = ids.elm_size assert isinstance(elm_size, int) and elm_size > 0, \ f'Invalid value for elm_size. Got: {elm_size}.' @@ -163,7 +162,7 @@ else: else: raise ValueError(f'Key {key} was not found.')"#; -pub(crate) const SEARCH_SORTED_LOWER: &str = r#"array_ptr = ids.array_ptr +pub const SEARCH_SORTED_LOWER: &str = r#"array_ptr = ids.array_ptr elm_size = ids.elm_size assert isinstance(elm_size, int) and elm_size > 0, \ f'Invalid value for elm_size. Got: {elm_size}.' @@ -183,7 +182,7 @@ for i in range(n_elms): else: ids.index = n_elms"#; -pub(crate) const SET_ADD: &str = r#"assert ids.elm_size > 0 +pub const SET_ADD: &str = r#"assert ids.elm_size > 0 assert ids.set_ptr <= ids.set_end_ptr elm_list = memory.get_range(ids.elm_ptr, ids.elm_size) for i in range(0, ids.set_end_ptr - ids.set_ptr, ids.elm_size): @@ -194,29 +193,29 @@ for i in range(0, ids.set_end_ptr - ids.set_ptr, ids.elm_size): else: ids.is_elm_in_set = 0"#; -pub(crate) const DEFAULT_DICT_NEW: &str = r#"if '__dict_manager' not in globals(): +pub const DEFAULT_DICT_NEW: &str = r#"if '__dict_manager' not in globals(): from starkware.cairo.common.dict import DictManager __dict_manager = DictManager() memory[ap] = __dict_manager.new_default_dict(segments, ids.default_value)"#; -pub(crate) const DICT_NEW: &str = r#"if '__dict_manager' not in globals(): +pub const DICT_NEW: &str = r#"if '__dict_manager' not in globals(): from starkware.cairo.common.dict import DictManager __dict_manager = DictManager() memory[ap] = __dict_manager.new_dict(segments, initial_dict) del initial_dict"#; -pub(crate) const DICT_READ: &str = r#"dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) +pub const DICT_READ: &str = r#"dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) dict_tracker.current_ptr += ids.DictAccess.SIZE ids.value = dict_tracker.data[ids.key]"#; -pub(crate) const DICT_WRITE: &str = r#"dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) +pub const DICT_WRITE: &str = r#"dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) dict_tracker.current_ptr += ids.DictAccess.SIZE ids.dict_ptr.prev_value = dict_tracker.data[ids.key] dict_tracker.data[ids.key] = ids.new_value"#; -pub(crate) const DICT_UPDATE: &str = r#"# Verify dict pointer and prev value. +pub const DICT_UPDATE: &str = r#"# Verify dict pointer and prev value. dict_tracker = __dict_manager.get_tracker(ids.dict_ptr) current_value = dict_tracker.data[ids.key] assert current_value == ids.prev_value, \ @@ -226,7 +225,7 @@ assert current_value == ids.prev_value, \ dict_tracker.data[ids.key] = ids.new_value dict_tracker.current_ptr += ids.DictAccess.SIZE"#; -pub(crate) const SQUASH_DICT: &str = r#"dict_access_size = ids.DictAccess.SIZE +pub const SQUASH_DICT: &str = r#"dict_access_size = ids.DictAccess.SIZE address = ids.dict_accesses.address_ assert ids.ptr_diff % dict_access_size == 0, \ 'Accesses array size must be divisible by DictAccess.SIZE' @@ -246,26 +245,26 @@ keys = sorted(access_indices.keys(), reverse=True) ids.big_keys = 1 if keys[0] >= range_check_builtin.bound else 0 ids.first_key = key = keys.pop()"#; -pub(crate) const SQUASH_DICT_INNER_SKIP_LOOP: &str = +pub const SQUASH_DICT_INNER_SKIP_LOOP: &str = "ids.should_skip_loop = 0 if current_access_indices else 1"; -pub(crate) const SQUASH_DICT_INNER_FIRST_ITERATION: &str = r#"current_access_indices = sorted(access_indices[key])[::-1] +pub const SQUASH_DICT_INNER_FIRST_ITERATION: &str = r#"current_access_indices = sorted(access_indices[key])[::-1] current_access_index = current_access_indices.pop() memory[ids.range_check_ptr] = current_access_index"#; -pub(crate) const SQUASH_DICT_INNER_CHECK_ACCESS_INDEX: &str = r#"new_access_index = current_access_indices.pop() +pub const SQUASH_DICT_INNER_CHECK_ACCESS_INDEX: &str = r#"new_access_index = current_access_indices.pop() ids.loop_temps.index_delta_minus1 = new_access_index - current_access_index - 1 current_access_index = new_access_index"#; -pub(crate) const SQUASH_DICT_INNER_CONTINUE_LOOP: &str = +pub const SQUASH_DICT_INNER_CONTINUE_LOOP: &str = "ids.loop_temps.should_continue = 1 if current_access_indices else 0"; -pub(crate) const SQUASH_DICT_INNER_ASSERT_LEN_KEYS: &str = "assert len(keys) == 0"; -pub(crate) const SQUASH_DICT_INNER_LEN_ASSERT: &str = "assert len(current_access_indices) == 0"; -pub(crate) const SQUASH_DICT_INNER_USED_ACCESSES_ASSERT: &str = +pub const SQUASH_DICT_INNER_ASSERT_LEN_KEYS: &str = "assert len(keys) == 0"; +pub const SQUASH_DICT_INNER_LEN_ASSERT: &str = "assert len(current_access_indices) == 0"; +pub const SQUASH_DICT_INNER_USED_ACCESSES_ASSERT: &str = "assert ids.n_used_accesses == len(access_indices[key])"; -pub(crate) const SQUASH_DICT_INNER_NEXT_KEY: &str = r#"assert len(keys) > 0, 'No keys left but remaining_accesses > 0.' +pub const SQUASH_DICT_INNER_NEXT_KEY: &str = r#"assert len(keys) > 0, 'No keys left but remaining_accesses > 0.' ids.next_key = key = keys.pop()"#; -pub(crate) const DICT_SQUASH_COPY_DICT: &str = r#"# Prepare arguments for dict_new. In particular, the same dictionary values should be copied +pub const DICT_SQUASH_COPY_DICT: &str = r#"# Prepare arguments for dict_new. In particular, the same dictionary values should be copied # to the new (squashed) dictionary. vm_enter_scope({ # Make __dict_manager accessible. @@ -274,28 +273,26 @@ vm_enter_scope({ 'initial_dict': dict(__dict_manager.get_dict(ids.dict_accesses_end)), })"#; -pub(crate) const DICT_SQUASH_UPDATE_PTR: &str = r#"# Update the DictTracker's current_ptr to point to the end of the squashed dict. +pub const DICT_SQUASH_UPDATE_PTR: &str = r#"# Update the DictTracker's current_ptr to point to the end of the squashed dict. __dict_manager.get_tracker(ids.squashed_dict_start).current_ptr = \ ids.squashed_dict_end.address_"#; -pub(crate) const BIGINT_TO_UINT256: &str = - "ids.low = (ids.x.d0 + ids.x.d1 * ids.BASE) & ((1 << 128) - 1)"; -pub(crate) const UINT256_ADD: &str = r#"sum_low = ids.a.low + ids.b.low +pub const BIGINT_TO_UINT256: &str = "ids.low = (ids.x.d0 + ids.x.d1 * ids.BASE) & ((1 << 128) - 1)"; +pub const UINT256_ADD: &str = r#"sum_low = ids.a.low + ids.b.low ids.carry_low = 1 if sum_low >= ids.SHIFT else 0 sum_high = ids.a.high + ids.b.high + ids.carry_low ids.carry_high = 1 if sum_high >= ids.SHIFT else 0"#; -pub(crate) const UINT256_SQRT: &str = r#"from starkware.python.math_utils import isqrt +pub const UINT256_SQRT: &str = r#"from starkware.python.math_utils import isqrt n = (ids.n.high << 128) + ids.n.low root = isqrt(n) assert 0 <= root < 2 ** 128 ids.root.low = root ids.root.high = 0"#; -pub(crate) const UINT256_SIGNED_NN: &str = - "memory[ap] = 1 if 0 <= (ids.a.high % PRIME) < 2 ** 127 else 0"; +pub const UINT256_SIGNED_NN: &str = "memory[ap] = 1 if 0 <= (ids.a.high % PRIME) < 2 ** 127 else 0"; -pub(crate) const UINT256_UNSIGNED_DIV_REM: &str = r#"a = (ids.a.high << 128) + ids.a.low +pub const UINT256_UNSIGNED_DIV_REM: &str = r#"a = (ids.a.high << 128) + ids.a.low div = (ids.div.high << 128) + ids.div.low quotient, remainder = divmod(a, div) @@ -304,7 +301,7 @@ ids.quotient.high = quotient >> 128 ids.remainder.low = remainder & ((1 << 128) - 1) ids.remainder.high = remainder >> 128"#; -pub(crate) const UINT256_MUL_DIV_MOD: &str = r#"a = (ids.a.high << 128) + ids.a.low +pub const UINT256_MUL_DIV_MOD: &str = r#"a = (ids.a.high << 128) + ids.a.low b = (ids.b.high << 128) + ids.b.low div = (ids.div.high << 128) + ids.div.low quotient, remainder = divmod(a * b, div) @@ -316,9 +313,9 @@ ids.quotient_high.high = quotient >> 384 ids.remainder.low = remainder & ((1 << 128) - 1) ids.remainder.high = remainder >> 128"#; -pub(crate) const USORT_ENTER_SCOPE: &str = +pub const USORT_ENTER_SCOPE: &str = "vm_enter_scope(dict(__usort_max_size = globals().get('__usort_max_size')))"; -pub(crate) const USORT_BODY: &str = r#"from collections import defaultdict +pub const USORT_BODY: &str = r#"from collections import defaultdict input_ptr = ids.input input_len = int(ids.input_len) @@ -338,18 +335,18 @@ ids.output_len = len(output) ids.output = segments.gen_arg(output) ids.multiplicities = segments.gen_arg([len(positions_dict[k]) for k in output])"#; -pub(crate) const USORT_VERIFY: &str = r#"last_pos = 0 +pub const USORT_VERIFY: &str = r#"last_pos = 0 positions = positions_dict[ids.value][::-1]"#; -pub(crate) const USORT_VERIFY_MULTIPLICITY_ASSERT: &str = "assert len(positions) == 0"; -pub(crate) const USORT_VERIFY_MULTIPLICITY_BODY: &str = r#"current_pos = positions.pop() +pub const USORT_VERIFY_MULTIPLICITY_ASSERT: &str = "assert len(positions) == 0"; +pub const USORT_VERIFY_MULTIPLICITY_BODY: &str = r#"current_pos = positions.pop() ids.next_item_index = current_pos - last_pos last_pos = current_pos + 1"#; -pub(crate) const BLAKE2S_COMPUTE: &str = r#"from starkware.cairo.common.cairo_blake2s.blake2s_utils import compute_blake2s_func +pub const BLAKE2S_COMPUTE: &str = r#"from starkware.cairo.common.cairo_blake2s.blake2s_utils import compute_blake2s_func compute_blake2s_func(segments=segments, output_ptr=ids.output)"#; -pub(crate) const BLAKE2S_FINALIZE: &str = r#"# Add dummy pairs of input and output. +pub const BLAKE2S_FINALIZE: &str = r#"# Add dummy pairs of input and output. from starkware.cairo.common.cairo_blake2s.blake2s_utils import IV, blake2s_compress _n_packed_instances = int(ids.N_PACKED_INSTANCES) @@ -370,36 +367,36 @@ output = blake2s_compress( padding = (modified_iv + message + [0, 0xffffffff] + output) * (_n_packed_instances - 1) segments.write_arg(ids.blake2s_ptr_end, padding)"#; -pub(crate) const BLAKE2S_ADD_UINT256: &str = r#"B = 32 +pub const BLAKE2S_ADD_UINT256: &str = r#"B = 32 MASK = 2 ** 32 - 1 segments.write_arg(ids.data, [(ids.low >> (B * i)) & MASK for i in range(4)]) segments.write_arg(ids.data + 4, [(ids.high >> (B * i)) & MASK for i in range(4)]"#; -pub(crate) const BLAKE2S_ADD_UINT256_BIGEND: &str = r#"B = 32 +pub const BLAKE2S_ADD_UINT256_BIGEND: &str = r#"B = 32 MASK = 2 ** 32 - 1 segments.write_arg(ids.data, [(ids.high >> (B * (3 - i))) & MASK for i in range(4)]) segments.write_arg(ids.data + 4, [(ids.low >> (B * (3 - i))) & MASK for i in range(4)])"#; -pub(crate) const NONDET_BIGINT3: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import split +pub const NONDET_BIGINT3: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import split segments.write_arg(ids.res.address_, split(value))"#; -pub(crate) const VERIFY_ZERO_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const VERIFY_ZERO_V1: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack q, r = divmod(pack(ids.val, PRIME), SECP_P) assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." ids.q = q % PRIME"#; -pub(crate) const VERIFY_ZERO_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P +pub const VERIFY_ZERO_V2: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P q, r = divmod(pack(ids.val, PRIME), SECP_P) assert r == 0, f"verify_zero: Invalid input {ids.val.d0, ids.val.d1, ids.val.d2}." ids.q = q % PRIME"#; -pub(crate) const REDUCE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const REDUCE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack value = pack(ids.x, PRIME) % SECP_P"#; -pub(crate) const UNSAFE_KECCAK: &str = r#"from eth_hash.auto import keccak +pub const UNSAFE_KECCAK: &str = r#"from eth_hash.auto import keccak data, length = ids.data, ids.length @@ -419,7 +416,7 @@ hashed = keccak(keccak_input) ids.high = int.from_bytes(hashed[:16], 'big') ids.low = int.from_bytes(hashed[16:32], 'big')"#; -pub(crate) const UNSAFE_KECCAK_FINALIZE: &str = r#"from eth_hash.auto import keccak +pub const UNSAFE_KECCAK_FINALIZE: &str = r#"from eth_hash.auto import keccak keccak_input = bytearray() n_elms = ids.keccak_state.end_ptr - ids.keccak_state.start_ptr for word in memory.get_range(ids.keccak_state.start_ptr, n_elms): @@ -428,25 +425,25 @@ hashed = keccak(keccak_input) ids.high = int.from_bytes(hashed[:16], 'big') ids.low = int.from_bytes(hashed[16:32], 'big')"#; -pub(crate) const IS_ZERO_NONDET: &str = "memory[ap] = to_felt_or_relocatable(x == 0)"; -pub(crate) const IS_ZERO_PACK: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const IS_ZERO_NONDET: &str = "memory[ap] = to_felt_or_relocatable(x == 0)"; +pub const IS_ZERO_PACK: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack x = pack(ids.x, PRIME) % SECP_P"#; -pub(crate) const IS_ZERO_ASSIGN_SCOPE_VARS: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P +pub const IS_ZERO_ASSIGN_SCOPE_VARS: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P from starkware.python.math_utils import div_mod value = x_inv = div_mod(1, x, SECP_P)"#; -pub(crate) const DIV_MOD_N_PACKED_DIVMOD: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack +pub const DIV_MOD_N_PACKED_DIVMOD: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import N, pack from starkware.python.math_utils import div_mod, safe_div a = pack(ids.a, PRIME) b = pack(ids.b, PRIME) value = res = div_mod(a, b, N)"#; -pub(crate) const DIV_MOD_N_SAFE_DIV: &str = r#"value = k = safe_div(res * b - a, N)"#; +pub const DIV_MOD_N_SAFE_DIV: &str = r#"value = k = safe_div(res * b - a, N)"#; -pub(crate) const GET_POINT_FROM_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const GET_POINT_FROM_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack x_cube_int = pack(ids.x_cube, PRIME) % SECP_P y_square_int = (x_cube_int + ids.BETA) % SECP_P @@ -458,13 +455,13 @@ if ids.v % 2 == y % 2: else: value = (-y) % SECP_P"#; -pub(crate) const EC_NEGATE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const EC_NEGATE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack y = pack(ids.point.y, PRIME) % SECP_P # The modulo operation in python always returns a nonnegative number. value = (-y) % SECP_P"#; -pub(crate) const EC_DOUBLE_SCOPE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const EC_DOUBLE_SCOPE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack from starkware.python.math_utils import ec_double_slope # Compute the slope. @@ -472,7 +469,7 @@ x = pack(ids.point.x, PRIME) y = pack(ids.point.y, PRIME) value = slope = ec_double_slope(point=(x, y), alpha=0, p=SECP_P)"#; -pub(crate) const EC_DOUBLE_SCOPE_WHITELIST: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const EC_DOUBLE_SCOPE_WHITELIST: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack from starkware.python.math_utils import div_mod # Compute the slope. @@ -480,7 +477,7 @@ x = pack(ids.pt.x, PRIME) y = pack(ids.pt.y, PRIME) value = slope = div_mod(3 * x ** 2, 2 * y, SECP_P)"#; -pub(crate) const COMPUTE_SLOPE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const COMPUTE_SLOPE: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack from starkware.python.math_utils import line_slope # Compute the slope. @@ -490,7 +487,7 @@ x1 = pack(ids.point1.x, PRIME) y1 = pack(ids.point1.y, PRIME) value = slope = line_slope(point1=(x0, y0), point2=(x1, y1), p=SECP_P)"#; -pub(crate) const COMPUTE_SLOPE_WHITELIST: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const COMPUTE_SLOPE_WHITELIST: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack from starkware.python.math_utils import div_mod # Compute the slope. @@ -500,7 +497,7 @@ x1 = pack(ids.pt1.x, PRIME) y1 = pack(ids.pt1.y, PRIME) value = slope = div_mod(y0 - y1, x0 - x1, SECP_P)"#; -pub(crate) const EC_DOUBLE_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const EC_DOUBLE_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack slope = pack(ids.slope, PRIME) x = pack(ids.point.x, PRIME) @@ -508,12 +505,11 @@ y = pack(ids.point.y, PRIME) value = new_x = (pow(slope, 2, SECP_P) - 2 * x) % SECP_P"#; -pub(crate) const EC_DOUBLE_ASSIGN_NEW_Y: &str = - r#"value = new_y = (slope * (x - new_x) - y) % SECP_P"#; +pub const EC_DOUBLE_ASSIGN_NEW_Y: &str = r#"value = new_y = (slope * (x - new_x) - y) % SECP_P"#; -pub(crate) const SHA256_INPUT: &str = r#"ids.full_word = int(ids.n_bytes >= 4)"#; +pub const SHA256_INPUT: &str = r#"ids.full_word = int(ids.n_bytes >= 4)"#; -pub(crate) const SHA256_MAIN: &str = r#"from starkware.cairo.common.cairo_sha256.sha256_utils import ( +pub const SHA256_MAIN: &str = r#"from starkware.cairo.common.cairo_sha256.sha256_utils import ( IV, compute_message_schedule, sha2_compress_function) _sha256_input_chunk_size_felts = int(ids.SHA256_INPUT_CHUNK_SIZE_FELTS) @@ -524,7 +520,7 @@ w = compute_message_schedule(memory.get_range( new_state = sha2_compress_function(IV, w) segments.write_arg(ids.output, new_state)"#; -pub(crate) const SHA256_FINALIZE: &str = r#"# Add dummy pairs of input and output. +pub const SHA256_FINALIZE: &str = r#"# Add dummy pairs of input and output. from starkware.cairo.common.cairo_sha256.sha256_utils import ( IV, compute_message_schedule, sha2_compress_function) @@ -539,16 +535,16 @@ output = sha2_compress_function(IV, w) padding = (message + IV + output) * (_block_size - 1) segments.write_arg(ids.sha256_ptr_end, padding)"#; -pub(crate) const KECCAK_WRITE_ARGS: &str = r#"segments.write_arg(ids.inputs, [ids.low % 2 ** 64, ids.low // 2 ** 64]) +pub const KECCAK_WRITE_ARGS: &str = r#"segments.write_arg(ids.inputs, [ids.low % 2 ** 64, ids.low // 2 ** 64]) segments.write_arg(ids.inputs + 2, [ids.high % 2 ** 64, ids.high // 2 ** 64])"#; -pub(crate) const COMPARE_BYTES_IN_WORD_NONDET: &str = +pub const COMPARE_BYTES_IN_WORD_NONDET: &str = r#"memory[ap] = to_felt_or_relocatable(ids.n_bytes < ids.BYTES_IN_WORD)"#; -pub(crate) const COMPARE_KECCAK_FULL_RATE_IN_BYTES_NONDET: &str = +pub const COMPARE_KECCAK_FULL_RATE_IN_BYTES_NONDET: &str = r#"memory[ap] = to_felt_or_relocatable(ids.n_bytes >= ids.KECCAK_FULL_RATE_IN_BYTES)"#; -pub(crate) const BLOCK_PERMUTATION: &str = r#"from starkware.cairo.common.keccak_utils.keccak_utils import keccak_func +pub const BLOCK_PERMUTATION: &str = r#"from starkware.cairo.common.keccak_utils.keccak_utils import keccak_func _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) assert 0 <= _keccak_state_size_felts < 100 @@ -558,7 +554,7 @@ segments.write_arg(ids.keccak_ptr, output_values)"#; // The 0.10.3 whitelist uses this variant (instead of the one used by the common library), but both hints have the same behaviour // We should check for future refactors that may discard one of the variants -pub(crate) const BLOCK_PERMUTATION_WHITELIST: &str = r#"from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func +pub const BLOCK_PERMUTATION_WHITELIST: &str = r#"from starkware.cairo.common.cairo_keccak.keccak_utils import keccak_func _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) assert 0 <= _keccak_state_size_felts < 100 @@ -566,7 +562,7 @@ output_values = keccak_func(memory.get_range( ids.keccak_ptr - _keccak_state_size_felts, _keccak_state_size_felts)) segments.write_arg(ids.keccak_ptr, output_values)"#; -pub(crate) const CAIRO_KECCAK_FINALIZE: &str = r#"# Add dummy pairs of input and output. +pub const CAIRO_KECCAK_FINALIZE: &str = r#"# Add dummy pairs of input and output. _keccak_state_size_felts = int(ids.KECCAK_STATE_SIZE_FELTS) _block_size = int(ids.BLOCK_SIZE) assert 0 <= _keccak_state_size_felts < 100 @@ -575,7 +571,7 @@ inp = [0] * _keccak_state_size_felts padding = (inp + keccak_func(inp)) * _block_size segments.write_arg(ids.keccak_ptr_end, padding)"#; -pub(crate) const FAST_EC_ADD_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack +pub const FAST_EC_ADD_ASSIGN_NEW_X: &str = r#"from starkware.cairo.common.cairo_secp.secp_utils import SECP_P, pack slope = pack(ids.slope, PRIME) x0 = pack(ids.point0.x, PRIME) @@ -584,43 +580,39 @@ y0 = pack(ids.point0.y, PRIME) value = new_x = (pow(slope, 2, SECP_P) - x0 - x1) % SECP_P"#; -pub(crate) const FAST_EC_ADD_ASSIGN_NEW_Y: &str = +pub const FAST_EC_ADD_ASSIGN_NEW_Y: &str = r#"value = new_y = (slope * (x0 - new_x) - y0) % SECP_P"#; -pub(crate) const EC_MUL_INNER: &str = r#"memory[ap] = (ids.scalar % PRIME) % 2"#; +pub const EC_MUL_INNER: &str = r#"memory[ap] = (ids.scalar % PRIME) % 2"#; -pub(crate) const RELOCATE_SEGMENT: &str = +pub const RELOCATE_SEGMENT: &str = r#"memory.add_relocation_rule(src_ptr=ids.src_ptr, dest_ptr=ids.dest_ptr)"#; -pub(crate) const TEMPORARY_ARRAY: &str = r#"ids.temporary_array = segments.add_temp_segment()"#; -pub(crate) const VERIFY_ECDSA_SIGNATURE: &str = +pub const TEMPORARY_ARRAY: &str = r#"ids.temporary_array = segments.add_temp_segment()"#; +pub const VERIFY_ECDSA_SIGNATURE: &str = r#"ecdsa_builtin.add_signature(ids.ecdsa_ptr.address_, (ids.signature_r, ids.signature_s))"#; -pub(crate) const SPLIT_OUTPUT_0: &str = "ids.output0_low = ids.output0 & ((1 << 128) - 1) +pub const SPLIT_OUTPUT_0: &str = "ids.output0_low = ids.output0 & ((1 << 128) - 1) ids.output0_high = ids.output0 >> 128"; -pub(crate) const SPLIT_OUTPUT_1: &str = "ids.output1_low = ids.output1 & ((1 << 128) - 1) +pub const SPLIT_OUTPUT_1: &str = "ids.output1_low = ids.output1 & ((1 << 128) - 1) ids.output1_high = ids.output1 >> 128"; -pub(crate) const SPLIT_INPUT_3: &str = "ids.high3, ids.low3 = divmod(memory[ids.inputs + 3], 256)"; -pub(crate) const SPLIT_INPUT_6: &str = - "ids.high6, ids.low6 = divmod(memory[ids.inputs + 6], 256 ** 2)"; -pub(crate) const SPLIT_INPUT_9: &str = - "ids.high9, ids.low9 = divmod(memory[ids.inputs + 9], 256 ** 3)"; -pub(crate) const SPLIT_INPUT_12: &str = +pub const SPLIT_INPUT_3: &str = "ids.high3, ids.low3 = divmod(memory[ids.inputs + 3], 256)"; +pub const SPLIT_INPUT_6: &str = "ids.high6, ids.low6 = divmod(memory[ids.inputs + 6], 256 ** 2)"; +pub const SPLIT_INPUT_9: &str = "ids.high9, ids.low9 = divmod(memory[ids.inputs + 9], 256 ** 3)"; +pub const SPLIT_INPUT_12: &str = "ids.high12, ids.low12 = divmod(memory[ids.inputs + 12], 256 ** 4)"; -pub(crate) const SPLIT_INPUT_15: &str = +pub const SPLIT_INPUT_15: &str = "ids.high15, ids.low15 = divmod(memory[ids.inputs + 15], 256 ** 5)"; -pub(crate) const SPLIT_N_BYTES: &str = +pub const SPLIT_N_BYTES: &str = "ids.n_words_to_copy, ids.n_bytes_left = divmod(ids.n_bytes, ids.BYTES_IN_WORD)"; -pub(crate) const SPLIT_OUTPUT_MID_LOW_HIGH: &str = - "tmp, ids.output1_low = divmod(ids.output1, 256 ** 7) +pub const SPLIT_OUTPUT_MID_LOW_HIGH: &str = "tmp, ids.output1_low = divmod(ids.output1, 256 ** 7) ids.output1_high, ids.output1_mid = divmod(tmp, 2 ** 128)"; -pub(crate) const NONDET_N_GREATER_THAN_10: &str = - "memory[ap] = to_felt_or_relocatable(ids.n >= 10)"; -pub(crate) const NONDET_N_GREATER_THAN_2: &str = "memory[ap] = to_felt_or_relocatable(ids.n >= 2)"; -pub(crate) const RANDOM_EC_POINT: &str = r#"from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME +pub const NONDET_N_GREATER_THAN_10: &str = "memory[ap] = to_felt_or_relocatable(ids.n >= 10)"; +pub const NONDET_N_GREATER_THAN_2: &str = "memory[ap] = to_felt_or_relocatable(ids.n >= 2)"; +pub const RANDOM_EC_POINT: &str = r#"from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME from starkware.python.math_utils import random_ec_point from starkware.python.utils import to_bytes @@ -629,7 +621,7 @@ from starkware.python.utils import to_bytes # (2) It's hard to choose inputs for which the builtin will fail. seed = b"".join(map(to_bytes, [ids.p.x, ids.p.y, ids.m, ids.q.x, ids.q.y])) ids.s.x, ids.s.y = random_ec_point(FIELD_PRIME, ALPHA, BETA, seed)"#; -pub(crate) const CHAINED_EC_OP_RANDOM_EC_POINT: &str = r#"from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME +pub const CHAINED_EC_OP_RANDOM_EC_POINT: &str = r#"from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME from starkware.python.math_utils import random_ec_point from starkware.python.utils import to_bytes @@ -656,7 +648,7 @@ seed = b"".join( ) ) ids.s.x, ids.s.y = random_ec_point(FIELD_PRIME, ALPHA, BETA, seed)"#; -pub(crate) const RECOVER_Y: &str = +pub const RECOVER_Y: &str = "from starkware.crypto.signature.signature import ALPHA, BETA, FIELD_PRIME from starkware.python.math_utils import recover_y ids.p.x = ids.x @@ -664,8 +656,7 @@ ids.p.x = ids.x ids.p.y = recover_y(ids.x, ALPHA, BETA, FIELD_PRIME)"; // The following hints support the lib https://github.com/NethermindEth/research-basic-Cairo-operations-big-integers/blob/main/lib/uint384.cairo -pub(crate) const UINT384_UNSIGNED_DIV_REM: &str = - "def split(num: int, num_bits_shift: int, length: int): +pub const UINT384_UNSIGNED_DIV_REM: &str = "def split(num: int, num_bits_shift: int, length: int): a = [] for _ in range(length): a.append( num & ((1 << num_bits_shift) - 1) ) @@ -691,15 +682,15 @@ remainder_split = split(remainder, num_bits_shift=128, length=3) ids.remainder.d0 = remainder_split[0] ids.remainder.d1 = remainder_split[1] ids.remainder.d2 = remainder_split[2]"; -pub(crate) const UINT384_SPLIT_128: &str = "ids.low = ids.a & ((1<<128) - 1) +pub const UINT384_SPLIT_128: &str = "ids.low = ids.a & ((1<<128) - 1) ids.high = ids.a >> 128"; -pub(crate) const ADD_NO_UINT384_CHECK: &str = "sum_d0 = ids.a.d0 + ids.b.d0 +pub const ADD_NO_UINT384_CHECK: &str = "sum_d0 = ids.a.d0 + ids.b.d0 ids.carry_d0 = 1 if sum_d0 >= ids.SHIFT else 0 sum_d1 = ids.a.d1 + ids.b.d1 + ids.carry_d0 ids.carry_d1 = 1 if sum_d1 >= ids.SHIFT else 0 sum_d2 = ids.a.d2 + ids.b.d2 + ids.carry_d1 ids.carry_d2 = 1 if sum_d2 >= ids.SHIFT else 0"; -pub(crate) const UINT384_UNSIGNED_DIV_REM_EXPANDED: &str = +pub const UINT384_UNSIGNED_DIV_REM_EXPANDED: &str = "def split(num: int, num_bits_shift: int, length: int): a = [] for _ in range(length): @@ -730,7 +721,7 @@ remainder_split = split(remainder, num_bits_shift=128, length=3) ids.remainder.d0 = remainder_split[0] ids.remainder.d1 = remainder_split[1] ids.remainder.d2 = remainder_split[2]"; -pub(crate) const UINT384_SQRT: &str = "from starkware.python.math_utils import isqrt +pub const UINT384_SQRT: &str = "from starkware.python.math_utils import isqrt def split(num: int, num_bits_shift: int, length: int): a = [] @@ -750,8 +741,7 @@ root_split = split(root, num_bits_shift=128, length=3) ids.root.d0 = root_split[0] ids.root.d1 = root_split[1] ids.root.d2 = root_split[2]"; -pub(crate) const UINT384_SIGNED_NN: &str = - "memory[ap] = 1 if 0 <= (ids.a.d2 % PRIME) < 2 ** 127 else 0"; +pub const UINT384_SIGNED_NN: &str = "memory[ap] = 1 if 0 <= (ids.a.d2 % PRIME) < 2 ** 127 else 0"; #[cfg(feature = "skip_next_instruction_hint")] -pub(crate) const SKIP_NEXT_INSTRUCTION: &str = "skip_next_instruction()"; +pub const SKIP_NEXT_INSTRUCTION: &str = "skip_next_instruction()";