@@ -2,11 +2,11 @@ use cairo_vm::types::builtin_name::BuiltinName;
22use cairo_vm:: types:: relocatable:: MaybeRelocatable ;
33use cairo_vm:: vm:: runners:: cairo_pie:: StrippedProgram ;
44use cairo_vm:: Felt252 ;
5- use starknet_crypto:: { pedersen_hash, poseidon_hash_many, FieldElement } ;
5+ use starknet_crypto:: { pedersen_hash, poseidon_hash_many, Felt } ;
66
77use super :: types:: HashFunc ;
88
9- type HashFunction = fn ( & FieldElement , & FieldElement ) -> FieldElement ;
9+ type HashFunction = fn ( & Felt , & Felt ) -> Felt ;
1010
1111#[ derive( thiserror_no_std:: Error , Debug ) ]
1212pub enum HashChainError {
@@ -27,10 +27,10 @@ pub enum ProgramHashError {
2727 #[ error( "Invalid program data: data contains relocatable(s)" ) ]
2828 InvalidProgramData ,
2929
30- /// Conversion from Felt252 to FieldElement failed. This is unlikely to happen
30+ /// Conversion from Felt252 to Felt failed. This is unlikely to happen
3131 /// unless the implementation of Felt252 changes and this code is not updated properly.
32- #[ error( "Conversion from Felt252 to FieldElement failed" ) ]
33- Felt252ToFieldElementConversionFailed ,
32+ #[ error( "Conversion from Felt252 to Felt failed" ) ]
33+ Felt252ToFeltConversionFailed ,
3434}
3535/*
3636 Computes a hash chain over the data, in the following order:
@@ -41,50 +41,54 @@ pub enum ProgramHashError {
4141 assert len(data) >= 1, f"len(data) for hash chain computation must be >= 1; got: {len(data)}."
4242 return functools.reduce(lambda x, y: hash_func(y, x), data[::-1])
4343*/
44- fn compute_hash_chain < ' a , I > (
45- data : I ,
46- hash_func : HashFunction ,
47- ) -> Result < FieldElement , HashChainError >
44+ fn compute_hash_chain < ' a , I > ( data : I , hash_func : HashFunction ) -> Result < Felt , HashChainError >
4845where
49- I : Iterator < Item = & ' a FieldElement > + DoubleEndedIterator ,
46+ I : Iterator < Item = & ' a Felt > + DoubleEndedIterator ,
5047{
5148 match data. copied ( ) . rev ( ) . reduce ( |x, y| hash_func ( & y, & x) ) {
5249 Some ( result) => Ok ( result) ,
5350 None => Err ( HashChainError :: EmptyData ) ,
5451 }
5552}
5653
57- /// Creates an instance of `FieldElement ` from a builtin name.
54+ /// Creates an instance of `Felt ` from a builtin name.
5855///
5956/// Converts the builtin name to bytes then attempts to create a field element from
6057/// these bytes. This function will fail if the builtin name is over 31 characters.
61- fn builtin_to_field_element ( builtin : & BuiltinName ) -> Result < FieldElement , ProgramHashError > {
58+ fn builtin_to_felt ( builtin : & BuiltinName ) -> Result < Felt , ProgramHashError > {
6259 // The Python implementation uses the builtin name without suffix
6360 let builtin_name = builtin. to_str ( ) ;
6461
65- FieldElement :: from_byte_slice_be ( builtin_name. as_bytes ( ) )
66- . map_err ( |_| ProgramHashError :: InvalidProgramBuiltin ( builtin. to_str ( ) ) )
62+ // TODO(idanh): not sure if this check is correct, documentation of Felt::from_bytes_be_slice
63+ // works in chunks of 32 bytes and not 31...
64+ if builtin_name. len ( ) > 31 {
65+ return Err ( ProgramHashError :: InvalidProgramBuiltin ( builtin. to_str ( ) ) ) ;
66+ }
67+ Ok ( Felt :: from_bytes_be_slice ( builtin_name. as_bytes ( ) ) )
6768}
6869
69- /// The `value: FieldElement ` is `pub(crate)` and there is no accessor.
70- /// This function converts a `Felt252` to a `FieldElement ` using a safe, albeit inefficient,
70+ /// The `value: Felt ` is `pub(crate)` and there is no accessor.
71+ /// This function converts a `Felt252` to a `Felt ` using a safe, albeit inefficient,
7172/// method.
72- fn felt_to_field_element ( felt : & Felt252 ) -> Result < FieldElement , ProgramHashError > {
73+ fn felt252_to_felt ( felt : & Felt252 ) -> Result < Felt , ProgramHashError > {
7374 let bytes = felt. to_bytes_be ( ) ;
74- FieldElement :: from_bytes_be ( & bytes)
75- . map_err ( |_e| ProgramHashError :: Felt252ToFieldElementConversionFailed )
75+ // Check if bytes length is over 31
76+ if bytes. len ( ) > 32 {
77+ return Err ( ProgramHashError :: Felt252ToFeltConversionFailed ) ;
78+ }
79+ Ok ( Felt :: from_bytes_be ( & bytes) )
7680}
7781
78- /// Converts a `MaybeRelocatable` into a `FieldElement ` value.
82+ /// Converts a `MaybeRelocatable` into a `Felt ` value.
7983///
8084/// Returns `InvalidProgramData` if `maybe_relocatable` is not an integer
81- fn maybe_relocatable_to_field_element (
85+ fn maybe_relocatable_to_felt (
8286 maybe_relocatable : & MaybeRelocatable ,
83- ) -> Result < FieldElement , ProgramHashError > {
87+ ) -> Result < Felt , ProgramHashError > {
8488 let felt = maybe_relocatable
8589 . get_int_ref ( )
8690 . ok_or ( ProgramHashError :: InvalidProgramData ) ?;
87- felt_to_field_element ( felt)
91+ felt252_to_felt ( felt)
8892}
8993
9094#[ allow( dead_code) ] // TODO: remove
@@ -103,33 +107,26 @@ pub fn compute_program_hash_chain(
103107 program : & StrippedProgram ,
104108 bootloader_version : usize ,
105109 program_hash_function : HashFunc ,
106- ) -> Result < FieldElement , ProgramHashError > {
110+ ) -> Result < Felt , ProgramHashError > {
107111 let program_main = program. main ;
108- let program_main = FieldElement :: from ( program_main) ;
112+ let program_main = Felt :: from ( program_main) ;
109113
110114 // Convert builtin names to field elements
111- let builtin_list: Result < Vec < FieldElement > , _ > = program
112- . builtins
113- . iter ( )
114- . map ( builtin_to_field_element)
115- . collect ( ) ;
115+ let builtin_list: Result < Vec < Felt > , _ > = program. builtins . iter ( ) . map ( builtin_to_felt) . collect ( ) ;
116116 let builtin_list = builtin_list?;
117117
118118 let program_header = vec ! [
119- FieldElement :: from( bootloader_version) ,
119+ Felt :: from( bootloader_version) ,
120120 program_main,
121- FieldElement :: from( program. builtins. len( ) ) ,
121+ Felt :: from( program. builtins. len( ) ) ,
122122 ] ;
123123
124- let program_data: Result < Vec < _ > , _ > = program
125- . data
126- . iter ( )
127- . map ( maybe_relocatable_to_field_element)
128- . collect ( ) ;
124+ let program_data: Result < Vec < _ > , _ > =
125+ program. data . iter ( ) . map ( maybe_relocatable_to_felt) . collect ( ) ;
129126 let program_data = program_data?;
130127
131128 let data_chain_len = program_header. len ( ) + builtin_list. len ( ) + program_data. len ( ) ;
132- let data_chain_len_vec = vec ! [ FieldElement :: from( data_chain_len) ] ;
129+ let data_chain_len_vec = vec ! [ Felt :: from( data_chain_len) ] ;
133130
134131 // Prepare a chain of iterators to feed to the hash function
135132 let data_chain = [
@@ -144,14 +141,14 @@ pub fn compute_program_hash_chain(
144141 compute_hash_chain ( data_chain. iter ( ) . flat_map ( |& v| v. iter ( ) ) , pedersen_hash) ?
145142 }
146143 HashFunc :: Poseidon => {
147- let data: Vec < FieldElement > = data_chain[ 1 ..]
144+ let data: Vec < Felt > = data_chain[ 1 ..]
148145 . iter ( )
149146 . flat_map ( |& v| v. iter ( ) . copied ( ) )
150147 . collect ( ) ;
151148 poseidon_hash_many ( & data)
152149 }
153150 // TODO(yairv): replace dummy with actual impl.
154- HashFunc :: Blake => FieldElement :: from ( 0x123456789u64 ) ,
151+ HashFunc :: Blake => Felt :: from ( 0x123456789u64 ) ,
155152 } ;
156153 Ok ( hash)
157154}
@@ -168,14 +165,10 @@ mod tests {
168165
169166 #[ test]
170167 fn test_compute_hash_chain ( ) {
171- let data: Vec < FieldElement > = vec ! [
172- FieldElement :: from( 1u64 ) ,
173- FieldElement :: from( 2u64 ) ,
174- FieldElement :: from( 3u64 ) ,
175- ] ;
168+ let data: Vec < Felt > = vec ! [ Felt :: from( 1u64 ) , Felt :: from( 2u64 ) , Felt :: from( 3u64 ) ] ;
176169 let expected_hash = pedersen_hash (
177- & FieldElement :: from ( 1u64 ) ,
178- & pedersen_hash ( & FieldElement :: from ( 2u64 ) , & FieldElement :: from ( 3u64 ) ) ,
170+ & Felt :: from ( 1u64 ) ,
171+ & pedersen_hash ( & Felt :: from ( 2u64 ) , & Felt :: from ( 3u64 ) ) ,
179172 ) ;
180173 let computed_hash = compute_hash_chain ( data. iter ( ) , pedersen_hash)
181174 . expect ( "Hash computation failed unexpectedly" ) ;
0 commit comments