diff --git a/cairo_programs/garaga.cairo b/cairo_programs/garaga.cairo new file mode 100644 index 0000000000..e301e934bc --- /dev/null +++ b/cairo_programs/garaga.cairo @@ -0,0 +1,344 @@ +%builtins range_check bitwise + +from starkware.cairo.common.uint256 import ( + Uint256, + uint256_reverse_endian, + uint256_unsigned_div_rem, + uint256_mul, + uint256_add, + uint256_pow2, +) + +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin +from starkware.cairo.common.registers import get_label_location +from starkware.cairo.common.math import unsigned_div_rem as felt_divmod, split_felt +from starkware.cairo.common.math_cmp import is_le +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.pow import pow + +// y MUST be a power of 2 +func bitwise_divmod{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(x: felt, y: felt) -> ( + q: felt, r: felt +) { + assert bitwise_ptr.x = x; + assert bitwise_ptr.y = y - 1; + let x_and_y = bitwise_ptr.x_and_y; + + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + return (q=(x - x_and_y) / y, r=x_and_y); +} +func felt_divmod_no_input_check{range_check_ptr}(value, div) -> (q: felt, r: felt) { + // let r = [range_check_ptr]; + // let q = [range_check_ptr + 1]; + // let range_check_ptr = range_check_ptr + 2; + alloc_locals; + local r; + local q; + %{ + 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) + %} + + assert [range_check_ptr] = div - 1 - r; + let range_check_ptr = range_check_ptr + 1; + // assert_le(r, div - 1); + + assert value = q * div + r; + return (q, r); +} + +func get_felt_bitlength{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(x: felt) -> felt { + alloc_locals; + local bit_length; + %{ + x = ids.x + ids.bit_length = x.bit_length() + %} + + // Next two lines Not necessary : will fail if pow2(bit_length) is too big, unknown cell. + // let le = is_le(bit_length, 252); + // assert le = 1; + assert bitwise_ptr[0].x = x; + let n = pow2(bit_length); + assert bitwise_ptr[0].y = n - 1; + tempvar word = bitwise_ptr[0].x_and_y; + assert word = x; + + assert bitwise_ptr[1].x = x; + + let n = pow2(bit_length - 1); + + assert bitwise_ptr[1].y = n - 1; + tempvar word = bitwise_ptr[1].x_and_y; + assert word = x - n; + + let bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + return bit_length; +} + +func pow2(i) -> felt { + let (data_address) = get_label_location(data); + return [data_address + i]; + + data: + dw 0x1; + dw 0x2; + dw 0x4; + dw 0x8; + dw 0x10; + dw 0x20; + dw 0x40; + dw 0x80; + dw 0x100; + dw 0x200; + dw 0x400; + dw 0x800; + dw 0x1000; + dw 0x2000; + dw 0x4000; + dw 0x8000; + dw 0x10000; + dw 0x20000; + dw 0x40000; + dw 0x80000; + dw 0x100000; + dw 0x200000; + dw 0x400000; + dw 0x800000; + dw 0x1000000; + dw 0x2000000; + dw 0x4000000; + dw 0x8000000; + dw 0x10000000; + dw 0x20000000; + dw 0x40000000; + dw 0x80000000; + dw 0x100000000; + dw 0x200000000; + dw 0x400000000; + dw 0x800000000; + dw 0x1000000000; + dw 0x2000000000; + dw 0x4000000000; + dw 0x8000000000; + dw 0x10000000000; + dw 0x20000000000; + dw 0x40000000000; + dw 0x80000000000; + dw 0x100000000000; + dw 0x200000000000; + dw 0x400000000000; + dw 0x800000000000; + dw 0x1000000000000; + dw 0x2000000000000; + dw 0x4000000000000; + dw 0x8000000000000; + dw 0x10000000000000; + dw 0x20000000000000; + dw 0x40000000000000; + dw 0x80000000000000; + dw 0x100000000000000; + dw 0x200000000000000; + dw 0x400000000000000; + dw 0x800000000000000; + dw 0x1000000000000000; + dw 0x2000000000000000; + dw 0x4000000000000000; + dw 0x8000000000000000; + dw 0x10000000000000000; + dw 0x20000000000000000; + dw 0x40000000000000000; + dw 0x80000000000000000; + dw 0x100000000000000000; + dw 0x200000000000000000; + dw 0x400000000000000000; + dw 0x800000000000000000; + dw 0x1000000000000000000; + dw 0x2000000000000000000; + dw 0x4000000000000000000; + dw 0x8000000000000000000; + dw 0x10000000000000000000; + dw 0x20000000000000000000; + dw 0x40000000000000000000; + dw 0x80000000000000000000; + dw 0x100000000000000000000; + dw 0x200000000000000000000; + dw 0x400000000000000000000; + dw 0x800000000000000000000; + dw 0x1000000000000000000000; + dw 0x2000000000000000000000; + dw 0x4000000000000000000000; + dw 0x8000000000000000000000; + dw 0x10000000000000000000000; + dw 0x20000000000000000000000; + dw 0x40000000000000000000000; + dw 0x80000000000000000000000; + dw 0x100000000000000000000000; + dw 0x200000000000000000000000; + dw 0x400000000000000000000000; + dw 0x800000000000000000000000; + dw 0x1000000000000000000000000; + dw 0x2000000000000000000000000; + dw 0x4000000000000000000000000; + dw 0x8000000000000000000000000; + dw 0x10000000000000000000000000; + dw 0x20000000000000000000000000; + dw 0x40000000000000000000000000; + dw 0x80000000000000000000000000; + dw 0x100000000000000000000000000; + dw 0x200000000000000000000000000; + dw 0x400000000000000000000000000; + dw 0x800000000000000000000000000; + dw 0x1000000000000000000000000000; + dw 0x2000000000000000000000000000; + dw 0x4000000000000000000000000000; + dw 0x8000000000000000000000000000; + dw 0x10000000000000000000000000000; + dw 0x20000000000000000000000000000; + dw 0x40000000000000000000000000000; + dw 0x80000000000000000000000000000; + dw 0x100000000000000000000000000000; + dw 0x200000000000000000000000000000; + dw 0x400000000000000000000000000000; + dw 0x800000000000000000000000000000; + dw 0x1000000000000000000000000000000; + dw 0x2000000000000000000000000000000; + dw 0x4000000000000000000000000000000; + dw 0x8000000000000000000000000000000; + dw 0x10000000000000000000000000000000; + dw 0x20000000000000000000000000000000; + dw 0x40000000000000000000000000000000; + dw 0x80000000000000000000000000000000; + dw 0x100000000000000000000000000000000; + dw 0x200000000000000000000000000000000; + dw 0x400000000000000000000000000000000; + dw 0x800000000000000000000000000000000; + dw 0x1000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000000000000000000000; + dw 0x800000000000000000000000000000000000000000000000000000000000; + dw 0x1000000000000000000000000000000000000000000000000000000000000; + dw 0x2000000000000000000000000000000000000000000000000000000000000; + dw 0x4000000000000000000000000000000000000000000000000000000000000; + dw 0x8000000000000000000000000000000000000000000000000000000000000; + dw 0x10000000000000000000000000000000000000000000000000000000000000; + dw 0x20000000000000000000000000000000000000000000000000000000000000; + dw 0x40000000000000000000000000000000000000000000000000000000000000; + dw 0x80000000000000000000000000000000000000000000000000000000000000; + dw 0x100000000000000000000000000000000000000000000000000000000000000; + dw 0x200000000000000000000000000000000000000000000000000000000000000; + dw 0x400000000000000000000000000000000000000000000000000000000000000; +} + +func main{range_check_ptr: felt, bitwise_ptr: BitwiseBuiltin*}() { + let x = get_felt_bitlength(42); + assert x = 6; + return (); +} diff --git a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs index 58fc12429d..1cca1d3118 100644 --- a/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs +++ b/src/hint_processor/builtin_hint_processor/builtin_hint_processor_definition.rs @@ -72,6 +72,7 @@ use felt::Felt252; use crate::hint_processor::builtin_hint_processor::skip_next_instruction::skip_next_instruction; use super::ec_utils::{chained_ec_op_random_ec_point_hint, random_ec_point_hint, recover_y_hint}; +use super::garaga::get_felt_bitlenght; use super::uint384::{ add_no_uint384_check, uint384_signed_nn, uint384_split_128, uint384_sqrt, uint384_unsigned_div_rem, uint384_unsigned_div_rem_expanded, @@ -350,6 +351,9 @@ impl HintProcessor for BuiltinHintProcessor { &hint_data.ap_tracking, ), hint_code::DIV_MOD_N_SAFE_DIV => div_mod_n_safe_div(exec_scopes), + hint_code::GET_FELT_BITLENGTH => { + get_felt_bitlenght(vm, &hint_data.ids_data, &hint_data.ap_tracking) + } hint_code::GET_POINT_FROM_X => get_point_from_x( vm, exec_scopes, diff --git a/src/hint_processor/builtin_hint_processor/garaga.rs b/src/hint_processor/builtin_hint_processor/garaga.rs new file mode 100644 index 0000000000..091819b129 --- /dev/null +++ b/src/hint_processor/builtin_hint_processor/garaga.rs @@ -0,0 +1,24 @@ +use std::collections::HashMap; + +use crate::{ + hint_processor::hint_processor_definition::HintReference, + serde::deserialize_program::ApTracking, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, +}; + +use super::hint_utils::{get_integer_from_var_name, insert_value_from_var_name}; + +/// Implements hint: +/// ```python +/// x = ids.x, +/// ids.bit_length = x.bit_length() +/// ``` +pub fn get_felt_bitlenght( + vm: &mut VirtualMachine, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + let x = get_integer_from_var_name("x", vm, ids_data, ap_tracking)?; + let bit_length = x.bits() as usize; + insert_value_from_var_name("bit_length", bit_length, vm, ids_data, ap_tracking) +} diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 1b6e765eb2..3a1f252f15 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -443,6 +443,9 @@ value = res = div_mod(a, b, N)"#; pub const DIV_MOD_N_SAFE_DIV: &str = r#"value = k = safe_div(res * b - a, N)"#; +pub const GET_FELT_BITLENGTH: &str = r#"x = ids.x +ids.bit_length = x.bit_length()"#; + 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 diff --git a/src/hint_processor/builtin_hint_processor/mod.rs b/src/hint_processor/builtin_hint_processor/mod.rs index 19348b601c..68225dee6d 100644 --- a/src/hint_processor/builtin_hint_processor/mod.rs +++ b/src/hint_processor/builtin_hint_processor/mod.rs @@ -6,6 +6,7 @@ pub mod dict_hint_utils; pub mod dict_manager; pub mod ec_utils; pub mod find_element_hint; +pub mod garaga; pub mod hint_code; pub mod hint_utils; pub mod keccak_utils; diff --git a/src/tests/cairo_run_test.rs b/src/tests/cairo_run_test.rs index ef2da718e2..7f800fc6f4 100644 --- a/src/tests/cairo_run_test.rs +++ b/src/tests/cairo_run_test.rs @@ -1315,3 +1315,10 @@ fn cairo_run_efficient_secp256r1_ec() { let program_data = include_bytes!("../../cairo_programs/efficient_secp256r1_ec.json"); run_program_simple(program_data.as_slice()); } + +#[test] +#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] +fn cairo_run_garaga() { + let program_data = include_bytes!("../../cairo_programs/garaga.json"); + run_program_simple(program_data.as_slice()); +}