From 48fb11a568b4aec8b19bce532c118fc04b87424e Mon Sep 17 00:00:00 2001 From: codyx Date: Mon, 2 Dec 2024 16:31:21 +0400 Subject: [PATCH 1/3] Add merkle hints --- cairo_vm_hints/src/hint_processor/mod.rs | 2 + cairo_vm_hints/src/hints/lib/merkle/mod.rs | 125 +++++++++++++++++++++ cairo_vm_hints/src/hints/lib/mod.rs | 1 + cairo_vm_hints/src/hints/vars.rs | 4 + 4 files changed, 132 insertions(+) create mode 100644 cairo_vm_hints/src/hints/lib/merkle/mod.rs diff --git a/cairo_vm_hints/src/hint_processor/mod.rs b/cairo_vm_hints/src/hint_processor/mod.rs index db00a187..74563159 100644 --- a/cairo_vm_hints/src/hint_processor/mod.rs +++ b/cairo_vm_hints/src/hint_processor/mod.rs @@ -97,6 +97,8 @@ impl CustomHintProcessor { hints.insert(lib::segments::SEGMENTS_ADD_EVM_MEMORIZER_OFFSET.into(), lib::segments::segments_add_evm_memorizer_offset); hints.insert(lib::segments::SEGMENTS_ADD_EVM_STARKNET_MEMORIZER_INDEX.into(), lib::segments::segments_add_evm_starknet_memorizer_index); hints.insert(lib::segments::SEGMENTS_ADD_STARKNET_MEMORIZER_OFFSET.into(), lib::segments::segments_add_starknet_memorizer_offset); + hints.insert(lib::merkle::HINT_TARGET_TASK_HASH.into(), lib::merkle::hint_target_task_hash); + hints.insert(lib::merkle::HINT_IS_LEFT_SMALLER.into(), lib::merkle::hint_is_left_smaller); hints } diff --git a/cairo_vm_hints/src/hints/lib/merkle/mod.rs b/cairo_vm_hints/src/hints/lib/merkle/mod.rs new file mode 100644 index 00000000..491bc459 --- /dev/null +++ b/cairo_vm_hints/src/hints/lib/merkle/mod.rs @@ -0,0 +1,125 @@ +use crate::hints::vars; +use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::HintProcessorData; +use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::{ + get_relocatable_from_var_name, insert_value_from_var_name, +}; +use cairo_vm::types::relocatable::MaybeRelocatable; +use cairo_vm::{ + types::exec_scope::ExecutionScopes, + vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, + Felt252, +}; +use num_bigint::BigInt; +use std::collections::HashMap; + +const TWO_POW_128: Felt252 = Felt252::from_hex_unchecked("0x0100000000000000000000000000000000"); + +pub const HINT_TARGET_TASK_HASH: &str = + "target_task_hash = hex(ids.task_hash.low + ids.task_hash.high*2**128)[2:] print(f\"Task Hash: 0x{target_task_hash}\")"; + +pub fn hint_target_task_hash( + vm: &mut VirtualMachine, + _exec_scope: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let task_hash_ptr = get_relocatable_from_var_name( + vars::ids::TASK_HASH, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?; + + let task_hash = vm + .get_continuous_range(task_hash_ptr, 2)? + .into_iter() + .map(|x| x.get_int().unwrap()) + .collect::>(); + + let task_hash_low = task_hash[0]; + let task_hash_high = task_hash[1]; + + // 2**128 + let multiplier = BigInt::from_bytes_be(num_bigint::Sign::Plus, &TWO_POW_128.to_bytes_be()); + + // task_hash_high * 2**128 + let multiplication = + BigInt::from_bytes_be(num_bigint::Sign::Plus, &task_hash_high.to_bytes_be()) * multiplier; + + // task_hash_low + `multiplication` + let result = BigInt::from_bytes_be(num_bigint::Sign::Plus, &task_hash_low.to_bytes_be()) + + multiplication; + + let target_task_hash = format!("{:x}", result); + + // TODO: add appropriate logger + println!("Task Hash: 0x{}", target_task_hash); + + Ok(()) +} + +pub const HINT_IS_LEFT_SMALLER: &str = + "def flip_endianess(val): val_hex = hex(val)[2:] if len(val_hex) % 2: val_hex = '0' + val_hex # Convert hex string to bytes byte_data = bytes.fromhex(val_hex) num = int.from_bytes(byte_data, byteorder=\"little\") return num # In LE Uint256, the low and high are reversed left = flip_endianess(ids.left.low) * 2**128 + flip_endianess(ids.left.high) right = flip_endianess(ids.right.low) * 2**128 + flip_endianess(ids.right.high) # Compare the values to derive correct hashing order if left < right: ids.is_left_smaller = 1 #print(f\"H({hex(left)}, {hex(right)}\") else: #print(f\"H({hex(right)}, {hex(left)}\") ids.is_left_smaller = 0"; + +fn flip_endianess(val: Felt252) -> Felt252 { + let mut bytes = val.to_bytes_be(); + bytes.reverse(); + + Felt252::from_bytes_be(&bytes) +} + +pub fn hint_is_left_smaller( + vm: &mut VirtualMachine, + _exec_scope: &mut ExecutionScopes, + hint_data: &HintProcessorData, + _constants: &HashMap, +) -> Result<(), HintError> { + let left_ptr = get_relocatable_from_var_name( + vars::ids::LEFT, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?; + + let left = vm + .get_continuous_range(left_ptr, 2)? + .into_iter() + .map(|x| x.get_int().unwrap()) + .collect::>(); + + let left_low = left[0]; + let left_high = left[1]; + + let right_ptr = get_relocatable_from_var_name( + vars::ids::RIGHT, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?; + + let right = vm + .get_continuous_range(right_ptr, 2)? + .into_iter() + .map(|x| x.get_int().unwrap()) + .collect::>(); + + let right_low = right[0]; + let right_high = right[1]; + + let left_flipped = flip_endianess(left_low) * TWO_POW_128 + flip_endianess(left_high); + let right_flipped = flip_endianess(right_low) * TWO_POW_128 + flip_endianess(right_high); + + let insert = if left_flipped < right_flipped { + Felt252::ONE + } else { + Felt252::ZERO + }; + + insert_value_from_var_name( + vars::ids::IS_LEFT_SMALLER, + MaybeRelocatable::Int(insert), + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + ) +} diff --git a/cairo_vm_hints/src/hints/lib/mod.rs b/cairo_vm_hints/src/hints/lib/mod.rs index 598627c8..c9df03d0 100644 --- a/cairo_vm_hints/src/hints/lib/mod.rs +++ b/cairo_vm_hints/src/hints/lib/mod.rs @@ -1,5 +1,6 @@ pub mod contract_bootloader; pub mod decoder; +pub mod merkle; pub mod print; pub mod rlp; pub mod segments; diff --git a/cairo_vm_hints/src/hints/vars.rs b/cairo_vm_hints/src/hints/vars.rs index 38e0ca48..4d656c49 100644 --- a/cairo_vm_hints/src/hints/vars.rs +++ b/cairo_vm_hints/src/hints/vars.rs @@ -29,4 +29,8 @@ pub mod ids { pub(crate) const SYSCALL_PTR: &str = "syscall_ptr"; pub(crate) const VALUE_LEN: &str = "ids.value_len"; pub(crate) const VALUE: &str = "ids.value"; + pub(crate) const IS_LEFT_SMALLER: &str = "ids.is_left_smaller"; + pub(crate) const LEFT: &str = "ids.left"; + pub(crate) const RIGHT: &str = "ids.right"; + pub(crate) const TASK_HASH: &str = "ids.task_hash"; } From fc6ea8889506919b09f6877d1d36677613fa3a5e Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Mon, 2 Dec 2024 15:14:21 +0100 Subject: [PATCH 2/3] refactor --- cairo_vm_hints/src/hints/lib/merkle/mod.rs | 96 +++++++++------------- 1 file changed, 39 insertions(+), 57 deletions(-) diff --git a/cairo_vm_hints/src/hints/lib/merkle/mod.rs b/cairo_vm_hints/src/hints/lib/merkle/mod.rs index 491bc459..2b4d7ea3 100644 --- a/cairo_vm_hints/src/hints/lib/merkle/mod.rs +++ b/cairo_vm_hints/src/hints/lib/merkle/mod.rs @@ -9,10 +9,11 @@ use cairo_vm::{ vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, Felt252, }; -use num_bigint::BigInt; +use num_bigint::BigUint; use std::collections::HashMap; -const TWO_POW_128: Felt252 = Felt252::from_hex_unchecked("0x0100000000000000000000000000000000"); +const FELT_TWO_POW_128: Felt252 = + Felt252::from_hex_unchecked("0x0100000000000000000000000000000000"); pub const HINT_TARGET_TASK_HASH: &str = "target_task_hash = hex(ids.task_hash.low + ids.task_hash.high*2**128)[2:] print(f\"Task Hash: 0x{target_task_hash}\")"; @@ -23,37 +24,25 @@ pub fn hint_target_task_hash( hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let task_hash_ptr = get_relocatable_from_var_name( - vars::ids::TASK_HASH, - vm, - &hint_data.ids_data, - &hint_data.ap_tracking, - )?; - let task_hash = vm - .get_continuous_range(task_hash_ptr, 2)? + .get_continuous_range( + get_relocatable_from_var_name( + vars::ids::TASK_HASH, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?, + 2, + )? .into_iter() .map(|x| x.get_int().unwrap()) .collect::>(); - let task_hash_low = task_hash[0]; - let task_hash_high = task_hash[1]; - - // 2**128 - let multiplier = BigInt::from_bytes_be(num_bigint::Sign::Plus, &TWO_POW_128.to_bytes_be()); - - // task_hash_high * 2**128 - let multiplication = - BigInt::from_bytes_be(num_bigint::Sign::Plus, &task_hash_high.to_bytes_be()) * multiplier; - - // task_hash_low + `multiplication` - let result = BigInt::from_bytes_be(num_bigint::Sign::Plus, &task_hash_low.to_bytes_be()) - + multiplication; - - let target_task_hash = format!("{:x}", result); + let target_task_hash = + task_hash[0].to_biguint() + FELT_TWO_POW_128.to_biguint() * task_hash[1].to_biguint(); // TODO: add appropriate logger - println!("Task Hash: 0x{}", target_task_hash); + println!("Task Hash: 0x{:x}", target_task_hash); Ok(()) } @@ -61,53 +50,46 @@ pub fn hint_target_task_hash( pub const HINT_IS_LEFT_SMALLER: &str = "def flip_endianess(val): val_hex = hex(val)[2:] if len(val_hex) % 2: val_hex = '0' + val_hex # Convert hex string to bytes byte_data = bytes.fromhex(val_hex) num = int.from_bytes(byte_data, byteorder=\"little\") return num # In LE Uint256, the low and high are reversed left = flip_endianess(ids.left.low) * 2**128 + flip_endianess(ids.left.high) right = flip_endianess(ids.right.low) * 2**128 + flip_endianess(ids.right.high) # Compare the values to derive correct hashing order if left < right: ids.is_left_smaller = 1 #print(f\"H({hex(left)}, {hex(right)}\") else: #print(f\"H({hex(right)}, {hex(left)}\") ids.is_left_smaller = 0"; -fn flip_endianess(val: Felt252) -> Felt252 { - let mut bytes = val.to_bytes_be(); - bytes.reverse(); - - Felt252::from_bytes_be(&bytes) -} - pub fn hint_is_left_smaller( vm: &mut VirtualMachine, _exec_scope: &mut ExecutionScopes, hint_data: &HintProcessorData, _constants: &HashMap, ) -> Result<(), HintError> { - let left_ptr = get_relocatable_from_var_name( - vars::ids::LEFT, - vm, - &hint_data.ids_data, - &hint_data.ap_tracking, - )?; - let left = vm - .get_continuous_range(left_ptr, 2)? + .get_continuous_range( + get_relocatable_from_var_name( + vars::ids::LEFT, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?, + 2, + )? .into_iter() .map(|x| x.get_int().unwrap()) .collect::>(); - let left_low = left[0]; - let left_high = left[1]; - - let right_ptr = get_relocatable_from_var_name( - vars::ids::RIGHT, - vm, - &hint_data.ids_data, - &hint_data.ap_tracking, - )?; - let right = vm - .get_continuous_range(right_ptr, 2)? + .get_continuous_range( + get_relocatable_from_var_name( + vars::ids::RIGHT, + vm, + &hint_data.ids_data, + &hint_data.ap_tracking, + )?, + 2, + )? .into_iter() .map(|x| x.get_int().unwrap()) .collect::>(); - let right_low = right[0]; - let right_high = right[1]; - - let left_flipped = flip_endianess(left_low) * TWO_POW_128 + flip_endianess(left_high); - let right_flipped = flip_endianess(right_low) * TWO_POW_128 + flip_endianess(right_high); + let left_flipped = BigUint::from_bytes_le(&left[0].to_bytes_be()) + * FELT_TWO_POW_128.to_biguint() + + BigUint::from_bytes_le(&left[1].to_bytes_be()); + let right_flipped = BigUint::from_bytes_le(&right[1].to_bytes_be()) + * FELT_TWO_POW_128.to_biguint() + + BigUint::from_bytes_le(&right[1].to_bytes_be()); let insert = if left_flipped < right_flipped { Felt252::ONE From 6020c23f733a93dec2e6bf98580d687225e572f8 Mon Sep 17 00:00:00 2001 From: Bartosz Nowak Date: Mon, 2 Dec 2024 15:15:52 +0100 Subject: [PATCH 3/3] sort --- cairo_vm_hints/src/hints/vars.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cairo_vm_hints/src/hints/vars.rs b/cairo_vm_hints/src/hints/vars.rs index 4d656c49..ac11ccfa 100644 --- a/cairo_vm_hints/src/hints/vars.rs +++ b/cairo_vm_hints/src/hints/vars.rs @@ -14,23 +14,23 @@ pub mod ids { pub(crate) const DEVISOR: &str = "ids.devisor"; pub(crate) const FIRST_BYTE: &str = "ids.first_byte"; pub(crate) const I: &str = "ids.i"; + pub(crate) const IS_LEFT_SMALLER: &str = "ids.is_left_smaller"; pub(crate) const IS_LONG: &str = "ids.is_long"; pub(crate) const ITEM_TYPE: &str = "ids.item_type"; + pub(crate) const LEFT: &str = "ids.left"; pub(crate) const N_BUILTINS: &str = "n_builtins"; pub(crate) const N_PROCESSED_WORDS: &str = "ids.n_processed_words"; pub(crate) const N_SELECTED_BUILTINS: &str = "n_selected_builtins"; pub(crate) const Q: &str = "ids.q"; pub(crate) const R: &str = "ids.r"; pub(crate) const RETURN_BUILTIN_PTRS: &str = "return_builtin_ptrs"; + pub(crate) const RIGHT: &str = "ids.right"; pub(crate) const RLP: &str = "ids.rlp"; pub(crate) const SELECT_BUILTIN: &str = "select_builtin"; pub(crate) const SELECTED_ENCODINGS: &str = "selected_encodings"; pub(crate) const SELECTED_PTRS: &str = "selected_ptrs"; pub(crate) const SYSCALL_PTR: &str = "syscall_ptr"; + pub(crate) const TASK_HASH: &str = "ids.task_hash"; pub(crate) const VALUE_LEN: &str = "ids.value_len"; pub(crate) const VALUE: &str = "ids.value"; - pub(crate) const IS_LEFT_SMALLER: &str = "ids.is_left_smaller"; - pub(crate) const LEFT: &str = "ids.left"; - pub(crate) const RIGHT: &str = "ids.right"; - pub(crate) const TASK_HASH: &str = "ids.task_hash"; }