From b4788b827e075b959bc6a9a6681d24a680316920 Mon Sep 17 00:00:00 2001 From: Idanh-starkware Date: Thu, 28 Aug 2025 07:43:27 +0300 Subject: [PATCH] bumping starknet crypto and renaming FieldElement to Felt --- Cargo.toml | 2 +- .../src/hints/builtin_usage_hints.rs | 18 ++-- .../src/hints/execute_task_hints.rs | 8 +- .../src/hints/program_hash.rs | 87 +++++++++---------- 4 files changed, 51 insertions(+), 64 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ab579040..ff98d5a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ num-traits = "0.2.19" regex = "1.11.1" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.142" -starknet-crypto = "0.6.2" +starknet-crypto = "0.7.4" starknet-types-core = "0.1.2" stwo_cairo_utils = { git = "https://github.com/starkware-libs/stwo-cairo", rev = "17a1b4cead265fe0312ef5bda771b12b5472d1c8" } stwo-cairo-adapter = { git = "https://github.com/starkware-libs/stwo-cairo", rev = "17a1b4cead265fe0312ef5bda771b12b5472d1c8" } diff --git a/crates/cairo-program-runner-lib/src/hints/builtin_usage_hints.rs b/crates/cairo-program-runner-lib/src/hints/builtin_usage_hints.rs index c204d45d..db88d5f2 100644 --- a/crates/cairo-program-runner-lib/src/hints/builtin_usage_hints.rs +++ b/crates/cairo-program-runner-lib/src/hints/builtin_usage_hints.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use super::{ - execute_task_hints::field_element_to_felt, fact_topologies::GPS_FACT_TOPOLOGY, + execute_task_hints::felt_to_felt252, fact_topologies::GPS_FACT_TOPOLOGY, types::FlexibleBuiltinUsageInput, PROGRAM_INPUT, }; use cairo_vm::{ @@ -16,7 +16,7 @@ use cairo_vm::{ vm::{errors::hint_errors::HintError, vm_core::VirtualMachine}, Felt252, }; -use starknet_crypto::{pedersen_hash, FieldElement}; +use starknet_crypto::{pedersen_hash, Felt}; /// Implements hint: /// %{ @@ -97,11 +97,8 @@ pub fn builtin_usage_set_pages_and_fact_topology( ) -> Result<(), HintError> { let output_ptr = get_ptr_from_var_name("output_ptr", vm, ids_data, ap_tracking)?; let output_ptr_val = vm.get_integer(output_ptr)?.into_owned(); - let ped_hash_val = pedersen_hash( - &FieldElement::from(123_usize), - &FieldElement::from(456_usize), - ); - if output_ptr_val != field_element_to_felt(ped_hash_val) { + let ped_hash_val = pedersen_hash(&Felt::from(123_usize), &Felt::from(456_usize)); + if output_ptr_val != felt_to_felt252(ped_hash_val) { return Err(HintError::CustomHint( format!("Pedersen hash mismatch: expected {ped_hash_val}, got {output_ptr_val}").into(), )); @@ -425,11 +422,8 @@ mod tests { vm.builtin_runners = vec![output_builtin_runner.into()]; // Load pedersen hash into output builtin_ptr - let ped_hash = pedersen_hash( - &FieldElement::from(left_pedersen_hash), - &FieldElement::from(456_usize), - ); - let ped_hash_felt = field_element_to_felt(ped_hash); + let ped_hash = pedersen_hash(&Felt::from(left_pedersen_hash), &Felt::from(456_usize)); + let ped_hash_felt = felt_to_felt252(ped_hash); let _ = vm .load_data( Relocatable::from((2, 0)), diff --git a/crates/cairo-program-runner-lib/src/hints/execute_task_hints.rs b/crates/cairo-program-runner-lib/src/hints/execute_task_hints.rs index 720d8267..e369b68e 100644 --- a/crates/cairo-program-runner-lib/src/hints/execute_task_hints.rs +++ b/crates/cairo-program-runner-lib/src/hints/execute_task_hints.rs @@ -21,7 +21,7 @@ use cairo_vm::vm::runners::builtin_runner::{OutputBuiltinRunner, OutputBuiltinSt use cairo_vm::vm::runners::cairo_pie::CairoPie; use cairo_vm::vm::vm_core::VirtualMachine; use cairo_vm::{any_box, Felt252}; -use starknet_crypto::FieldElement; +use starknet_crypto::Felt; use super::types::HashFunc; use super::utils::{get_identifier, get_program_from_task, get_program_identifies}; @@ -33,7 +33,7 @@ use crate::hints::program_loader::ProgramLoader; use crate::hints::types::{BootloaderVersion, Task}; use crate::hints::vars; -pub fn field_element_to_felt(field_element: FieldElement) -> Felt252 { +pub fn felt_to_felt252(field_element: Felt) -> Felt252 { let bytes = field_element.to_bytes_be(); Felt252::from_bytes_be(&bytes) } @@ -175,7 +175,7 @@ pub fn validate_hash( .map_err(|e| { HintError::CustomHint(format!("Could not compute program hash: {e}").into_boxed_str()) })?; - let computed_program_hash = field_element_to_felt(computed_program_hash); + let computed_program_hash = felt_to_felt252(computed_program_hash); if program_hash != computed_program_hash { return Err(HintError::AssertionFailed( @@ -543,7 +543,7 @@ pub fn bootloader_validate_hash( .map_err(|e| { HintError::CustomHint(format!("Could not compute program hash: {e}").into_boxed_str()) })?; - let computed_program_hash = field_element_to_felt(computed_program_hash); + let computed_program_hash = felt_to_felt252(computed_program_hash); if program_hash != computed_program_hash { return Err(HintError::AssertionFailed( "Computed hash does not match input" diff --git a/crates/cairo-program-runner-lib/src/hints/program_hash.rs b/crates/cairo-program-runner-lib/src/hints/program_hash.rs index e7ee70f0..5108ed73 100644 --- a/crates/cairo-program-runner-lib/src/hints/program_hash.rs +++ b/crates/cairo-program-runner-lib/src/hints/program_hash.rs @@ -2,11 +2,11 @@ use cairo_vm::types::builtin_name::BuiltinName; use cairo_vm::types::relocatable::MaybeRelocatable; use cairo_vm::vm::runners::cairo_pie::StrippedProgram; use cairo_vm::Felt252; -use starknet_crypto::{pedersen_hash, poseidon_hash_many, FieldElement}; +use starknet_crypto::{pedersen_hash, poseidon_hash_many, Felt}; use super::types::HashFunc; -type HashFunction = fn(&FieldElement, &FieldElement) -> FieldElement; +type HashFunction = fn(&Felt, &Felt) -> Felt; #[derive(thiserror_no_std::Error, Debug)] pub enum HashChainError { @@ -27,10 +27,10 @@ pub enum ProgramHashError { #[error("Invalid program data: data contains relocatable(s)")] InvalidProgramData, - /// Conversion from Felt252 to FieldElement failed. This is unlikely to happen + /// Conversion from Felt252 to Felt failed. This is unlikely to happen /// unless the implementation of Felt252 changes and this code is not updated properly. - #[error("Conversion from Felt252 to FieldElement failed")] - Felt252ToFieldElementConversionFailed, + #[error("Conversion from Felt252 to Felt failed")] + Felt252ToFeltConversionFailed, } /* Computes a hash chain over the data, in the following order: @@ -41,12 +41,9 @@ pub enum ProgramHashError { assert len(data) >= 1, f"len(data) for hash chain computation must be >= 1; got: {len(data)}." return functools.reduce(lambda x, y: hash_func(y, x), data[::-1]) */ -fn compute_hash_chain<'a, I>( - data: I, - hash_func: HashFunction, -) -> Result +fn compute_hash_chain<'a, I>(data: I, hash_func: HashFunction) -> Result where - I: Iterator + DoubleEndedIterator, + I: Iterator + DoubleEndedIterator, { match data.copied().rev().reduce(|x, y| hash_func(&y, &x)) { Some(result) => Ok(result), @@ -54,37 +51,44 @@ where } } -/// Creates an instance of `FieldElement` from a builtin name. +/// Creates an instance of `Felt` from a builtin name. /// /// Converts the builtin name to bytes then attempts to create a field element from /// these bytes. This function will fail if the builtin name is over 31 characters. -fn builtin_to_field_element(builtin: &BuiltinName) -> Result { +fn builtin_to_felt(builtin: &BuiltinName) -> Result { // The Python implementation uses the builtin name without suffix let builtin_name = builtin.to_str(); - FieldElement::from_byte_slice_be(builtin_name.as_bytes()) - .map_err(|_| ProgramHashError::InvalidProgramBuiltin(builtin.to_str())) + // TODO(idanh): not sure if this check is correct, documentation of Felt::from_bytes_be_slice + // works in chunks of 32 bytes and not 31... + if builtin_name.len() > 31 { + return Err(ProgramHashError::InvalidProgramBuiltin(builtin.to_str())); + } + Ok(Felt::from_bytes_be_slice(builtin_name.as_bytes())) } -/// The `value: FieldElement` is `pub(crate)` and there is no accessor. -/// This function converts a `Felt252` to a `FieldElement` using a safe, albeit inefficient, +/// The `value: Felt` is `pub(crate)` and there is no accessor. +/// This function converts a `Felt252` to a `Felt` using a safe, albeit inefficient, /// method. -fn felt_to_field_element(felt: &Felt252) -> Result { +fn felt252_to_felt(felt: &Felt252) -> Result { let bytes = felt.to_bytes_be(); - FieldElement::from_bytes_be(&bytes) - .map_err(|_e| ProgramHashError::Felt252ToFieldElementConversionFailed) + // Check if bytes length is over 31 + if bytes.len() > 32 { + return Err(ProgramHashError::Felt252ToFeltConversionFailed); + } + Ok(Felt::from_bytes_be(&bytes)) } -/// Converts a `MaybeRelocatable` into a `FieldElement` value. +/// Converts a `MaybeRelocatable` into a `Felt` value. /// /// Returns `InvalidProgramData` if `maybe_relocatable` is not an integer -fn maybe_relocatable_to_field_element( +fn maybe_relocatable_to_felt( maybe_relocatable: &MaybeRelocatable, -) -> Result { +) -> Result { let felt = maybe_relocatable .get_int_ref() .ok_or(ProgramHashError::InvalidProgramData)?; - felt_to_field_element(felt) + felt252_to_felt(felt) } #[allow(dead_code)] // TODO: remove @@ -103,33 +107,26 @@ pub fn compute_program_hash_chain( program: &StrippedProgram, bootloader_version: usize, program_hash_function: HashFunc, -) -> Result { +) -> Result { let program_main = program.main; - let program_main = FieldElement::from(program_main); + let program_main = Felt::from(program_main); // Convert builtin names to field elements - let builtin_list: Result, _> = program - .builtins - .iter() - .map(builtin_to_field_element) - .collect(); + let builtin_list: Result, _> = program.builtins.iter().map(builtin_to_felt).collect(); let builtin_list = builtin_list?; let program_header = vec![ - FieldElement::from(bootloader_version), + Felt::from(bootloader_version), program_main, - FieldElement::from(program.builtins.len()), + Felt::from(program.builtins.len()), ]; - let program_data: Result, _> = program - .data - .iter() - .map(maybe_relocatable_to_field_element) - .collect(); + let program_data: Result, _> = + program.data.iter().map(maybe_relocatable_to_felt).collect(); let program_data = program_data?; let data_chain_len = program_header.len() + builtin_list.len() + program_data.len(); - let data_chain_len_vec = vec![FieldElement::from(data_chain_len)]; + let data_chain_len_vec = vec![Felt::from(data_chain_len)]; // Prepare a chain of iterators to feed to the hash function let data_chain = [ @@ -144,14 +141,14 @@ pub fn compute_program_hash_chain( compute_hash_chain(data_chain.iter().flat_map(|&v| v.iter()), pedersen_hash)? } HashFunc::Poseidon => { - let data: Vec = data_chain[1..] + let data: Vec = data_chain[1..] .iter() .flat_map(|&v| v.iter().copied()) .collect(); poseidon_hash_many(&data) } // TODO(yairv): replace dummy with actual impl. - HashFunc::Blake => FieldElement::from(0x123456789u64), + HashFunc::Blake => Felt::from(0x123456789u64), }; Ok(hash) } @@ -168,14 +165,10 @@ mod tests { #[test] fn test_compute_hash_chain() { - let data: Vec = vec![ - FieldElement::from(1u64), - FieldElement::from(2u64), - FieldElement::from(3u64), - ]; + let data: Vec = vec![Felt::from(1u64), Felt::from(2u64), Felt::from(3u64)]; let expected_hash = pedersen_hash( - &FieldElement::from(1u64), - &pedersen_hash(&FieldElement::from(2u64), &FieldElement::from(3u64)), + &Felt::from(1u64), + &pedersen_hash(&Felt::from(2u64), &Felt::from(3u64)), ); let computed_hash = compute_hash_chain(data.iter(), pedersen_hash) .expect("Hash computation failed unexpectedly");