From 86077f2a966d079939b7db6ce60102cdd973cdae Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 17:29:24 -0300 Subject: [PATCH 01/14] Add normalize address hints --- Cargo.lock | 8 +-- .../builtin_hint_processor_definition.rs | 13 ++++ .../builtin_hint_processor/hint_code.rs | 8 +++ .../builtin_hint_processor/mod.rs | 1 + .../normalize_address.rs | 68 +++++++++++++++++++ 5 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 src/hint_processor/builtin_hint_processor/normalize_address.rs diff --git a/Cargo.lock b/Cargo.lock index 4298e181a5..5528f2568c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cairo-felt" -version = "0.2.2" +version = "0.3.0-rc1" dependencies = [ "lazy_static", "num-bigint", @@ -187,7 +187,7 @@ dependencies = [ [[package]] name = "cairo-take_until_unbalanced" -version = "0.24.1" +version = "0.24.2-rc1" dependencies = [ "nom", "wasm-bindgen-test", @@ -195,7 +195,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "0.2.2" +version = "0.3.0-rc1" dependencies = [ "anyhow", "assert_matches", @@ -231,7 +231,7 @@ dependencies = [ [[package]] name = "cairo-vm-cli" -version = "0.1.0" +version = "0.3.0-rc1" dependencies = [ "bincode", "cairo-vm", 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 519c35b312..49e1ff2dd1 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 @@ -71,6 +71,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::normalize_address::{normalize_address_set_is_250, normalize_address_set_is_small}; pub struct HintProcessorData { pub code: String, @@ -449,6 +450,18 @@ impl HintProcessor for BuiltinHintProcessor { chained_ec_op_random_ec_point_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking) } hint_code::RECOVER_Y => recover_y_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking), + hint_code::NORMALIZE_ADDRESS_SET_IS_250_HINT => normalize_address_set_is_250( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), + hint_code::NORMALIZE_ADDRESS_SET_IS_SMALL_HINT => normalize_address_set_is_small( + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + constants, + ), #[cfg(feature = "skip_next_instruction_hint")] hint_code::SKIP_NEXT_INSTRUCTION => skip_next_instruction(vm), code => Err(HintError::UnknownHint(code.to_string())), diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 5ee26e2deb..2fcfaaca91 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -608,5 +608,13 @@ from starkware.python.math_utils import recover_y ids.p.x = ids.x # This raises an exception if `x` is not on the curve. ids.p.y = recover_y(ids.x, ALPHA, BETA, FIELD_PRIME)"; +pub(crate) const NORMALIZE_ADDRESS_SET_IS_250_HINT: &str = + "ids.is_250 = 1 if ids.addr < 2**250 else 0"; +pub(crate) const NORMALIZE_ADDRESS_SET_IS_SMALL_HINT: &str = r#"# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME. + ADDR_BOUND = ids.ADDR_BOUND % PRIME + assert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and ( + ADDR_BOUND * 2 > PRIME), \ + 'normalize_address() cannot be used with the current constants.' + ids.is_small = 1 if ids.addr < ADDR_BOUND else 0"#; #[cfg(feature = "skip_next_instruction_hint")] pub(crate) const SKIP_NEXT_INSTRUCTION: &str = "skip_next_instruction()"; diff --git a/src/hint_processor/builtin_hint_processor/mod.rs b/src/hint_processor/builtin_hint_processor/mod.rs index 75abd3a6e9..2a162036e7 100644 --- a/src/hint_processor/builtin_hint_processor/mod.rs +++ b/src/hint_processor/builtin_hint_processor/mod.rs @@ -12,6 +12,7 @@ pub mod keccak_utils; pub mod math_utils; pub mod memcpy_hint_utils; pub mod memset_utils; +pub mod normalize_address; pub mod poseidon_utils; pub mod pow_utils; pub mod secp; diff --git a/src/hint_processor/builtin_hint_processor/normalize_address.rs b/src/hint_processor/builtin_hint_processor/normalize_address.rs new file mode 100644 index 0000000000..0d7b199e9f --- /dev/null +++ b/src/hint_processor/builtin_hint_processor/normalize_address.rs @@ -0,0 +1,68 @@ +use core::ops::Shl; + +use crate::hint_processor::builtin_hint_processor::hint_utils::get_integer_from_var_name; +use crate::stdlib::{collections::HashMap, prelude::*}; +use crate::utils::CAIRO_PRIME; +use crate::vm::errors::hint_errors::HintError; +use felt::Felt252; +use lazy_static::lazy_static; +use num_traits::One; + +use crate::{ + hint_processor::hint_processor_definition::HintReference, + serde::deserialize_program::ApTracking, vm::vm_core::VirtualMachine, +}; + +use super::hint_utils::insert_value_from_var_name; + +const ADDR_BOUND: &str = "starkware.starknet.common.storage.ADDR_BOUND"; +lazy_static! { + static ref HALF_PRIME: Felt252 = Felt252::from(&*CAIRO_PRIME / 2_u32); +} + +/* Implements hint: +# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME. + ADDR_BOUND = ids.ADDR_BOUND % PRIME + assert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and ( + ADDR_BOUND * 2 > PRIME), \ + 'normalize_address() cannot be used with the current constants.' + ids.is_small = 1 if ids.addr < ADDR_BOUND else 0" + */ +pub(crate) fn normalize_address_set_is_small( + vm: &mut VirtualMachine, + ids_data: &HashMap, + ap_tracking: &ApTracking, + constants: &HashMap, +) -> Result<(), HintError> { + let addr_bound = constants + .get(ADDR_BOUND) + .ok_or(HintError::MissingConstant("ADDR_BOUND"))?; + let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?; + if addr_bound <= &Felt252::one().shl(250_usize) + || addr_bound > &Felt252::one().shl(251_usize) + || addr_bound <= &*HALF_PRIME + { + return Err(HintError::AssertionFailed(format!( + "assert (2**250 < {} <= 2**251) and (2 * 2**250 < PRIME) and ( + {} * 2 > PRIME); normalize_address() cannot be used with the current constants.", + addr_bound, addr_bound + ))); + } + + let is_small = Felt252::from((*addr < *addr_bound) as usize); + insert_value_from_var_name("is_small", is_small, vm, ids_data, ap_tracking) +} + +/* Implements Hint: +ids.is_250 = 1 if ids.addr < 2**250 else 0 + */ +pub(crate) fn normalize_address_set_is_250( + vm: &mut VirtualMachine, + ids_data: &HashMap, + ap_tracking: &ApTracking, + _constants: &HashMap, +) -> Result<(), HintError> { + let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?; + let is_250 = Felt252::from((*addr < Felt252::one().shl(250_usize)) as usize); + insert_value_from_var_name("is_250", is_250, vm, ids_data, ap_tracking) +} From e65bf601a5bb57944d05db94f6a31abd1c30e5df Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 17:35:24 -0300 Subject: [PATCH 02/14] Revert "Add normalize address hints" This reverts commit 86077f2a966d079939b7db6ce60102cdd973cdae. --- Cargo.lock | 8 +-- .../builtin_hint_processor_definition.rs | 13 ---- .../builtin_hint_processor/hint_code.rs | 8 --- .../builtin_hint_processor/mod.rs | 1 - .../normalize_address.rs | 68 ------------------- 5 files changed, 4 insertions(+), 94 deletions(-) delete mode 100644 src/hint_processor/builtin_hint_processor/normalize_address.rs diff --git a/Cargo.lock b/Cargo.lock index 5528f2568c..4298e181a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cairo-felt" -version = "0.3.0-rc1" +version = "0.2.2" dependencies = [ "lazy_static", "num-bigint", @@ -187,7 +187,7 @@ dependencies = [ [[package]] name = "cairo-take_until_unbalanced" -version = "0.24.2-rc1" +version = "0.24.1" dependencies = [ "nom", "wasm-bindgen-test", @@ -195,7 +195,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "0.3.0-rc1" +version = "0.2.2" dependencies = [ "anyhow", "assert_matches", @@ -231,7 +231,7 @@ dependencies = [ [[package]] name = "cairo-vm-cli" -version = "0.3.0-rc1" +version = "0.1.0" dependencies = [ "bincode", "cairo-vm", 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 49e1ff2dd1..519c35b312 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 @@ -71,7 +71,6 @@ 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::normalize_address::{normalize_address_set_is_250, normalize_address_set_is_small}; pub struct HintProcessorData { pub code: String, @@ -450,18 +449,6 @@ impl HintProcessor for BuiltinHintProcessor { chained_ec_op_random_ec_point_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking) } hint_code::RECOVER_Y => recover_y_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking), - hint_code::NORMALIZE_ADDRESS_SET_IS_250_HINT => normalize_address_set_is_250( - vm, - &hint_data.ids_data, - &hint_data.ap_tracking, - constants, - ), - hint_code::NORMALIZE_ADDRESS_SET_IS_SMALL_HINT => normalize_address_set_is_small( - vm, - &hint_data.ids_data, - &hint_data.ap_tracking, - constants, - ), #[cfg(feature = "skip_next_instruction_hint")] hint_code::SKIP_NEXT_INSTRUCTION => skip_next_instruction(vm), code => Err(HintError::UnknownHint(code.to_string())), diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 2fcfaaca91..5ee26e2deb 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -608,13 +608,5 @@ from starkware.python.math_utils import recover_y ids.p.x = ids.x # This raises an exception if `x` is not on the curve. ids.p.y = recover_y(ids.x, ALPHA, BETA, FIELD_PRIME)"; -pub(crate) const NORMALIZE_ADDRESS_SET_IS_250_HINT: &str = - "ids.is_250 = 1 if ids.addr < 2**250 else 0"; -pub(crate) const NORMALIZE_ADDRESS_SET_IS_SMALL_HINT: &str = r#"# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME. - ADDR_BOUND = ids.ADDR_BOUND % PRIME - assert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and ( - ADDR_BOUND * 2 > PRIME), \ - 'normalize_address() cannot be used with the current constants.' - ids.is_small = 1 if ids.addr < ADDR_BOUND else 0"#; #[cfg(feature = "skip_next_instruction_hint")] pub(crate) const SKIP_NEXT_INSTRUCTION: &str = "skip_next_instruction()"; diff --git a/src/hint_processor/builtin_hint_processor/mod.rs b/src/hint_processor/builtin_hint_processor/mod.rs index 2a162036e7..75abd3a6e9 100644 --- a/src/hint_processor/builtin_hint_processor/mod.rs +++ b/src/hint_processor/builtin_hint_processor/mod.rs @@ -12,7 +12,6 @@ pub mod keccak_utils; pub mod math_utils; pub mod memcpy_hint_utils; pub mod memset_utils; -pub mod normalize_address; pub mod poseidon_utils; pub mod pow_utils; pub mod secp; diff --git a/src/hint_processor/builtin_hint_processor/normalize_address.rs b/src/hint_processor/builtin_hint_processor/normalize_address.rs deleted file mode 100644 index 0d7b199e9f..0000000000 --- a/src/hint_processor/builtin_hint_processor/normalize_address.rs +++ /dev/null @@ -1,68 +0,0 @@ -use core::ops::Shl; - -use crate::hint_processor::builtin_hint_processor::hint_utils::get_integer_from_var_name; -use crate::stdlib::{collections::HashMap, prelude::*}; -use crate::utils::CAIRO_PRIME; -use crate::vm::errors::hint_errors::HintError; -use felt::Felt252; -use lazy_static::lazy_static; -use num_traits::One; - -use crate::{ - hint_processor::hint_processor_definition::HintReference, - serde::deserialize_program::ApTracking, vm::vm_core::VirtualMachine, -}; - -use super::hint_utils::insert_value_from_var_name; - -const ADDR_BOUND: &str = "starkware.starknet.common.storage.ADDR_BOUND"; -lazy_static! { - static ref HALF_PRIME: Felt252 = Felt252::from(&*CAIRO_PRIME / 2_u32); -} - -/* Implements hint: -# Verify the assumptions on the relationship between 2**250, ADDR_BOUND and PRIME. - ADDR_BOUND = ids.ADDR_BOUND % PRIME - assert (2**250 < ADDR_BOUND <= 2**251) and (2 * 2**250 < PRIME) and ( - ADDR_BOUND * 2 > PRIME), \ - 'normalize_address() cannot be used with the current constants.' - ids.is_small = 1 if ids.addr < ADDR_BOUND else 0" - */ -pub(crate) fn normalize_address_set_is_small( - vm: &mut VirtualMachine, - ids_data: &HashMap, - ap_tracking: &ApTracking, - constants: &HashMap, -) -> Result<(), HintError> { - let addr_bound = constants - .get(ADDR_BOUND) - .ok_or(HintError::MissingConstant("ADDR_BOUND"))?; - let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?; - if addr_bound <= &Felt252::one().shl(250_usize) - || addr_bound > &Felt252::one().shl(251_usize) - || addr_bound <= &*HALF_PRIME - { - return Err(HintError::AssertionFailed(format!( - "assert (2**250 < {} <= 2**251) and (2 * 2**250 < PRIME) and ( - {} * 2 > PRIME); normalize_address() cannot be used with the current constants.", - addr_bound, addr_bound - ))); - } - - let is_small = Felt252::from((*addr < *addr_bound) as usize); - insert_value_from_var_name("is_small", is_small, vm, ids_data, ap_tracking) -} - -/* Implements Hint: -ids.is_250 = 1 if ids.addr < 2**250 else 0 - */ -pub(crate) fn normalize_address_set_is_250( - vm: &mut VirtualMachine, - ids_data: &HashMap, - ap_tracking: &ApTracking, - _constants: &HashMap, -) -> Result<(), HintError> { - let addr = get_integer_from_var_name("addr", vm, ids_data, ap_tracking)?; - let is_250 = Felt252::from((*addr < Felt252::one().shl(250_usize)) as usize); - insert_value_from_var_name("is_250", is_250, vm, ids_data, ap_tracking) -} From e88d901f8f1214f7d636c32a059195eefb9e1a16 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 18:02:20 -0300 Subject: [PATCH 03/14] Add uint256_mul_div_mod hint --- Cargo.lock | 8 +- .../builtin_hint_processor/hint_code.rs | 12 +++ .../builtin_hint_processor/uint256_utils.rs | 77 +++++++++++++++++++ 3 files changed, 93 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4298e181a5..5528f2568c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -175,7 +175,7 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cairo-felt" -version = "0.2.2" +version = "0.3.0-rc1" dependencies = [ "lazy_static", "num-bigint", @@ -187,7 +187,7 @@ dependencies = [ [[package]] name = "cairo-take_until_unbalanced" -version = "0.24.1" +version = "0.24.2-rc1" dependencies = [ "nom", "wasm-bindgen-test", @@ -195,7 +195,7 @@ dependencies = [ [[package]] name = "cairo-vm" -version = "0.2.2" +version = "0.3.0-rc1" dependencies = [ "anyhow", "assert_matches", @@ -231,7 +231,7 @@ dependencies = [ [[package]] name = "cairo-vm-cli" -version = "0.1.0" +version = "0.3.0-rc1" dependencies = [ "bincode", "cairo-vm", diff --git a/src/hint_processor/builtin_hint_processor/hint_code.rs b/src/hint_processor/builtin_hint_processor/hint_code.rs index 5ee26e2deb..5d38e6380f 100644 --- a/src/hint_processor/builtin_hint_processor/hint_code.rs +++ b/src/hint_processor/builtin_hint_processor/hint_code.rs @@ -295,6 +295,18 @@ 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 +b = (ids.b.high << 128) + ids.b.low +div = (ids.div.high << 128) + ids.div.low +quotient, remainder = divmod(a * b, div) + +ids.quotient_low.low = quotient & ((1 << 128) - 1) +ids.quotient_low.high = (quotient >> 128) & ((1 << 128) - 1) +ids.quotient_high.low = (quotient >> 256) & ((1 << 128) - 1) +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 = "vm_enter_scope(dict(__usort_max_size = globals().get('__usort_max_size')))"; pub(crate) const USORT_BODY: &str = r#"from collections import defaultdict diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 01cec6b97c..1d02d5a9a3 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -217,6 +217,83 @@ pub fn uint256_unsigned_div_rem( Ok(()) } +/* Implements Hint: +%{ +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) + +ids.quotient_low.low = quotient & ((1 << 128) - 1) +ids.quotient_low.high = (quotient >> 128) & ((1 << 128) - 1) +ids.quotient_high.low = (quotient >> 256) & ((1 << 128) - 1) +ids.quotient_high.high = quotient >> 384 +ids.remainder.low = remainder & ((1 << 128) - 1) +ids.remainder.high = remainder >> 128 +%} +*/ +pub fn uint256_mul_div_mod( + vm: &mut VirtualMachine, + ids_data: &HashMap, + ap_tracking: &ApTracking, +) -> Result<(), HintError> { + // Extract variables + let a_addr = get_relocatable_from_var_name("a", vm, ids_data, ap_tracking)?; + let b_addr = get_relocatable_from_var_name("b", vm, ids_data, ap_tracking)?; + let div_addr = get_relocatable_from_var_name("div", vm, ids_data, ap_tracking)?; + let quotient_low_addr = + get_relocatable_from_var_name("quotient_low", vm, ids_data, ap_tracking)?; + let quotient_high_addr = + get_relocatable_from_var_name("quotient_high", vm, ids_data, ap_tracking)?; + let remainder_addr = get_relocatable_from_var_name("remainder", vm, ids_data, ap_tracking)?; + + let a_low = vm.get_integer(a_addr)?; + let a_high = vm.get_integer((a_addr + 1_usize)?)?; + let b_low = vm.get_integer(b_addr)?; + let b_high = vm.get_integer((b_addr + 1_usize)?)?; + let div_low = vm.get_integer(div_addr)?; + let div_high = vm.get_integer((div_addr + 1_usize)?)?; + let a_low = a_low.as_ref(); + let a_high = a_high.as_ref(); + let b_low = b_low.as_ref(); + let b_high = b_high.as_ref(); + let div_low = div_low.as_ref(); + let div_high = div_high.as_ref(); + + // Main Logic + let a = a_high.shl(128_usize) + a_low; + let b = b_high.shl(128_usize) + b_low; + let div = div_high.shl(128_usize) + div_low; + let (quotient, remainder) = div_rem(a * b, div); + + // ids.quotient_low.low + vm.insert_value( + quotient_low_addr, + "ient & &(Felt252::one().shr(128_u32) - 1_u32), + )?; + // ids.quotient_low.high + vm.insert_value( + (quotient_low_addr + 1)?, + ("ient).shr(128_u32) & &(Felt252::one().shl(128_u32) - 1_u32), + )?; + // ids.quotient_high.low + vm.insert_value( + quotient_high_addr, + ("ient).shr(256_u32) & &(Felt252::one().shl(128_u32) - 1_u32), + )?; + // ids.quotient_high.high + vm.insert_value((quotient_high_addr + 1)?, ("ient).shr(384_u32))?; + //ids.remainder.low + vm.insert_value( + remainder_addr, + &remainder & &(Felt252::one().shl(128_u32) - 1_u32), + )?; + //ids.remainder.high + vm.insert_value((remainder_addr + 1)?, remainder.shr(128_u32))?; + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; From 373e0412bcf2313261f470bd8035cd31d57774d9 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 18:08:14 -0300 Subject: [PATCH 04/14] Add hint to match --- .../builtin_hint_processor_definition.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 519c35b312..a8b7dabb49 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 @@ -52,7 +52,8 @@ use crate::{ squash_dict_inner_used_accesses_assert, }, uint256_utils::{ - split_64, uint256_add, uint256_signed_nn, uint256_sqrt, uint256_unsigned_div_rem, + split_64, uint256_add, uint256_mul_div_mod, uint256_signed_nn, uint256_sqrt, + uint256_unsigned_div_rem, }, usort::{ usort_body, usort_enter_scope, verify_multiplicity_assert, @@ -449,6 +450,9 @@ impl HintProcessor for BuiltinHintProcessor { chained_ec_op_random_ec_point_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking) } hint_code::RECOVER_Y => recover_y_hint(vm, &hint_data.ids_data, &hint_data.ap_tracking), + hint_code::UINT256_MUL_DIV_MOD => { + uint256_mul_div_mod(vm, &hint_data.ids_data, &hint_data.ap_tracking) + } #[cfg(feature = "skip_next_instruction_hint")] hint_code::SKIP_NEXT_INSTRUCTION => skip_next_instruction(vm), code => Err(HintError::UnknownHint(code.to_string())), From 8275c613f375b0e75a413901aa63b108f7fd4df0 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 18:21:10 -0300 Subject: [PATCH 05/14] Expand uint256 integration test --- cairo_programs/uint256.cairo | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cairo_programs/uint256.cairo b/cairo_programs/uint256.cairo index d6bc3f9a29..4a1e6a2e9d 100644 --- a/cairo_programs/uint256.cairo +++ b/cairo_programs/uint256.cairo @@ -8,6 +8,7 @@ from starkware.cairo.common.uint256 import ( uint256_signed_nn, uint256_unsigned_div_rem, uint256_mul, + uint256_mul_div_mod ) from starkware.cairo.common.alloc import alloc @@ -57,6 +58,24 @@ func main{range_check_ptr: felt}() { assert b_quotient = Uint256(1, 0); assert b_remainder = Uint256(340282366920938463463374607431768211377, 0); + let (a_quotient_low, a_quotient_high, a_remainder) = uint256_mul_div_mod( + Uint256(89, 72), + Uint256(3, 7), + Uint256(107, 114), + ); + assert a_quotient_low = Uint256(143276786071974089879315624181797141668, 4); + assert a_quotient_high = Uint256(0, 0); + assert a_remainder = Uint256(322372768661941702228460154409043568767, 101); + + let (b_quotient_low, b_quotient_high, b_remainder) = uint256_mul_div_mod( + Uint256(-3618502788666131213697322783095070105282824848410658236509717448704103809099, 2), + Uint256(1, 1), + Uint256(5, 2), + ); + assert b_quotient_low = Uint256(170141183460469231731687303715884105688, 1); + assert b_quotient_high = Uint256(0, 0); + assert b_remainder = Uint256(170141183460469231731687303715884105854, 1); + let (mult_low_a, mult_high_a) = uint256_mul(Uint256(59, 2), Uint256(10, 0)); assert mult_low_a = Uint256(590, 20); assert mult_high_a = Uint256(0, 0); From a7d9c98f2a57ae3b2769bdcd4d24ac9408476615 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 18:28:35 -0300 Subject: [PATCH 06/14] use u128::MAX --- .../builtin_hint_processor/uint256_utils.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 1d02d5a9a3..447476e160 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -274,20 +274,17 @@ pub fn uint256_mul_div_mod( // ids.quotient_low.high vm.insert_value( (quotient_low_addr + 1)?, - ("ient).shr(128_u32) & &(Felt252::one().shl(128_u32) - 1_u32), + ("ient).shr(128_u32) & &Felt252::new(u128::MAX), )?; // ids.quotient_high.low vm.insert_value( quotient_high_addr, - ("ient).shr(256_u32) & &(Felt252::one().shl(128_u32) - 1_u32), + ("ient).shr(256_u32) & &Felt252::new(u128::MAX), )?; // ids.quotient_high.high vm.insert_value((quotient_high_addr + 1)?, ("ient).shr(384_u32))?; //ids.remainder.low - vm.insert_value( - remainder_addr, - &remainder & &(Felt252::one().shl(128_u32) - 1_u32), - )?; + vm.insert_value(remainder_addr, &remainder & &Felt252::new(u128::MAX))?; //ids.remainder.high vm.insert_value((remainder_addr + 1)?, remainder.shr(128_u32))?; From f417afaf4c20d6f68542e79db264dcad32f83f56 Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 18:30:25 -0300 Subject: [PATCH 07/14] Fix value --- src/hint_processor/builtin_hint_processor/uint256_utils.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 447476e160..807614426e 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -267,10 +267,7 @@ pub fn uint256_mul_div_mod( let (quotient, remainder) = div_rem(a * b, div); // ids.quotient_low.low - vm.insert_value( - quotient_low_addr, - "ient & &(Felt252::one().shr(128_u32) - 1_u32), - )?; + vm.insert_value(quotient_low_addr, "ient & &Felt252::new(u128::MAX))?; // ids.quotient_low.high vm.insert_value( (quotient_low_addr + 1)?, From 30fec4ddfa83403f9a514e6b4366086a63f6cc3b Mon Sep 17 00:00:00 2001 From: Federica Date: Mon, 10 Apr 2023 18:55:57 -0300 Subject: [PATCH 08/14] Manage quotient & remainder as BigUint --- .../builtin_hint_processor/uint256_utils.rs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 807614426e..f635cb6c99 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -14,7 +14,8 @@ use crate::{ vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, }; use felt::Felt252; -use num_integer::div_rem; +use num_bigint::BigUint; +use num_integer::{div_rem, Integer}; use num_traits::{One, Signed, Zero}; /* Implements hint: @@ -264,26 +265,35 @@ pub fn uint256_mul_div_mod( let a = a_high.shl(128_usize) + a_low; let b = b_high.shl(128_usize) + b_low; let div = div_high.shl(128_usize) + div_low; - let (quotient, remainder) = div_rem(a * b, div); + let (quotient, remainder) = (a.to_biguint() * b.to_biguint()).div_mod_floor(&div.to_biguint()); // ids.quotient_low.low - vm.insert_value(quotient_low_addr, "ient & &Felt252::new(u128::MAX))?; + vm.insert_value( + quotient_low_addr, + Felt252::from("ient & &BigUint::from(u128::MAX)), + )?; // ids.quotient_low.high vm.insert_value( (quotient_low_addr + 1)?, - ("ient).shr(128_u32) & &Felt252::new(u128::MAX), + Felt252::from(("ient).shr(128_u32) & &BigUint::from(u128::MAX)), )?; // ids.quotient_high.low vm.insert_value( quotient_high_addr, - ("ient).shr(256_u32) & &Felt252::new(u128::MAX), + Felt252::from(("ient).shr(256_u32) & &BigUint::from(u128::MAX)), )?; // ids.quotient_high.high - vm.insert_value((quotient_high_addr + 1)?, ("ient).shr(384_u32))?; + vm.insert_value( + (quotient_high_addr + 1)?, + Felt252::from(("ient).shr(384_u32)), + )?; //ids.remainder.low - vm.insert_value(remainder_addr, &remainder & &Felt252::new(u128::MAX))?; + vm.insert_value( + remainder_addr, + Felt252::from(&remainder & &BigUint::from(u128::MAX)), + )?; //ids.remainder.high - vm.insert_value((remainder_addr + 1)?, remainder.shr(128_u32))?; + vm.insert_value((remainder_addr + 1)?, Felt252::from(remainder.shr(128_u32)))?; Ok(()) } From 8304cd6a74a19559bf294dbf80511075e2b4d2b6 Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 11 Apr 2023 10:31:33 -0300 Subject: [PATCH 09/14] Add test for hint --- .../builtin_hint_processor/uint256_utils.rs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index f635cb6c99..e81bb9e335 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -301,6 +301,7 @@ pub fn uint256_mul_div_mod( #[cfg(test)] mod tests { use super::*; + use crate::hint_processor::builtin_hint_processor::hint_code; use crate::vm::vm_memory::memory_segments::MemorySegmentManager; use crate::{ any_box, @@ -654,4 +655,54 @@ mod tests { z == MaybeRelocatable::from(Felt252::new(10)) ); } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_mul_div_mod_ok() { + let mut vm = vm_with_range_check!(); + //Initialize fp + vm.run_context.fp = 10; + //Create hint_data + let ids_data = non_continuous_ids_data![ + ("a", -8), + ("b", -6), + ("div", -4), + ("quotient_low", 0), + ("quotient_high", 2), + ("remainder", 4) + ]; + //Insert ids into memory + vm.segments = segments![ + ((1, 2), 89), + ((1, 3), 72), + ((1, 4), 3), + ((1, 5), 7), + ((1, 6), 107), + ((1, 7), 114) + ]; + //Execute the hint + assert_matches!( + run_hint!(vm, ids_data, hint_code::UINT256_MUL_DIV_MOD), + Ok(()) + ); + //Check hint memory inserts + //ids.quotient.low, ids.quotient.high, ids.remainder.low, ids.remainder.high + check_memory![ + vm.segments.memory, + ((1, 10), 143276786071974089879315624181797141668), + ((1, 11), 4), + ((1, 12), 0), + ((1, 13), 0), + //((1, 14), 322372768661941702228460154409043568767), + ((1, 15), 101) + ]; + assert_eq!( + vm.segments + .memory + .get_integer((1, 14).into()) + .unwrap() + .as_ref(), + &felt_str!("322372768661941702228460154409043568767") + ) + } } From 27696af6664874b44b01db682025e2be53a7ff21 Mon Sep 17 00:00:00 2001 From: Federica Date: Tue, 11 Apr 2023 10:41:40 -0300 Subject: [PATCH 10/14] Add test for hint --- .../builtin_hint_processor/uint256_utils.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index e81bb9e335..854a7e61a4 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -705,4 +705,34 @@ mod tests { &felt_str!("322372768661941702228460154409043568767") ) } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_mul_div_mod_missing_ids() { + let mut vm = vm_with_range_check!(); + //Initialize fp + vm.run_context.fp = 10; + //Create hint_data + let ids_data = non_continuous_ids_data![ + ("a", -8), + ("b", -6), + ("div", -4), + ("quotient", 0), + ("remainder", 2) + ]; + //Insert ids into memory + vm.segments = segments![ + ((1, 2), 89), + ((1, 3), 72), + ((1, 4), 3), + ((1, 5), 7), + ((1, 6), 107), + ((1, 7), 114) + ]; + //Execute the hint + assert_matches!( + run_hint!(vm, ids_data, hint_code::UINT256_MUL_DIV_MOD), + Err(HintError::UnknownIdentifier(s)) if s == "quotient_low" + ); + } } From 962c8b868334abce5c628ce6b9432570ec0cb38f Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 13 Apr 2023 12:54:12 -0300 Subject: [PATCH 11/14] Add misc test --- .../builtin_hint_processor/uint256_utils.rs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/hint_processor/builtin_hint_processor/uint256_utils.rs b/src/hint_processor/builtin_hint_processor/uint256_utils.rs index 854a7e61a4..3002b9e295 100644 --- a/src/hint_processor/builtin_hint_processor/uint256_utils.rs +++ b/src/hint_processor/builtin_hint_processor/uint256_utils.rs @@ -656,6 +656,39 @@ mod tests { ); } + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn run_unsigned_div_rem_invalid_memory_insert_2() { + let hint_code = "a = (ids.a.high << 128) + ids.a.low\ndiv = (ids.div.high << 128) + ids.div.low\nquotient, remainder = divmod(a, div)\n\nids.quotient.low = quotient & ((1 << 128) - 1)\nids.quotient.high = quotient >> 128\nids.remainder.low = remainder & ((1 << 128) - 1)\nids.remainder.high = remainder >> 128"; + let mut vm = vm_with_range_check!(); + //Initialize fp + vm.run_context.fp = 10; + //Create hint_data + let ids_data = + non_continuous_ids_data![("a", -6), ("div", -4), ("quotient", 0), ("remainder", 2)]; + //Insert ids into memory + vm.segments = segments![ + ((1, 4), 89), + ((1, 5), 72), + ((1, 6), 3), + ((1, 7), 7), + ((1, 11), 1) + ]; + //Execute the hint + assert_matches!( + run_hint!(vm, ids_data, hint_code), + Err(HintError::Memory( + MemoryError::InconsistentMemory( + x, + y, + z, + ) + )) if x == Relocatable::from((1, 11)) && + y == MaybeRelocatable::from(Felt252::one()) && + z == MaybeRelocatable::from(Felt252::zero()) + ); + } + #[test] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] fn run_mul_div_mod_ok() { From 18e6e859e8014ec05cac8c1b1f6ddffac14b6951 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 13 Apr 2023 15:13:48 -0300 Subject: [PATCH 12/14] Add changelog entry --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1c8956cac..52abbea571 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,25 @@ #### Upcoming Changes +* Implement hint on `uint256_mul_div_mod`[#957] + BuiltinHintProcessor now supports the following hint: + + ```python + 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) + + ids.quotient_low.low = quotient & ((1 << 128) - 1) + ids.quotient_low.high = (quotient >> 128) & ((1 << 128) - 1) + ids.quotient_high.low = (quotient >> 256) & ((1 << 128) - 1) + ids.quotient_high.high = quotient >> 384 + ids.remainder.low = remainder & ((1 << 128) - 1) + ids.remainder.high = remainder >> 128" + ``` + + Used by the common library function `uint256_mul_div_mod` + * Move `Memory` into `MemorySegmentManager` [#830](https://github.com/lambdaclass/cairo-rs/pull/830) * Structural changes: * Remove `memory: Memory` field from `VirtualMachine` From 660680aeb5891f808b810433175537d4da8c4780 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 13 Apr 2023 15:15:04 -0300 Subject: [PATCH 13/14] fmt --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52abbea571..4f644f2b4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ BuiltinHintProcessor now supports the following hint: ```python - a = (ids.a.high << 128) + ids.a.low + 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) From 432ae24d53dcf71a164a612a62f119f7731b1f51 Mon Sep 17 00:00:00 2001 From: Federica Date: Thu, 13 Apr 2023 15:16:35 -0300 Subject: [PATCH 14/14] fmt --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f644f2b4d..def8da9ca9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,9 @@ #### Upcoming Changes -* Implement hint on `uint256_mul_div_mod`[#957] - BuiltinHintProcessor now supports the following hint: +* Implement hint on `uint256_mul_div_mod`[#957](https://github.com/lambdaclass/cairo-rs/pull/957) + + `BuiltinHintProcessor` now supports the following hint: ```python a = (ids.a.high << 128) + ids.a.low