@@ -11,24 +11,39 @@ use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
11
11
use cairo_vm:: vm:: vm_core:: VirtualMachine ;
12
12
use starknet_api:: transaction:: TransactionHash ;
13
13
14
+ use crate :: hint_processor:: constants:: BUILTIN_INSTANCE_SIZES ;
14
15
use crate :: hints:: error:: OsHintError ;
15
16
use crate :: hints:: vars:: { CairoStruct , Ids } ;
16
17
use crate :: vm_utils:: get_address_of_nested_fields;
17
18
18
19
#[ derive( Debug , thiserror:: Error ) ]
19
20
pub enum OsLoggerError {
21
+ #[ error(
22
+ "Builtin {builtin} in self and in the enter call counter are not in the same segment: \
23
+ {self_ptr}, {enter_ptr}."
24
+ ) ]
25
+ BuiltinsNotInSameSegment { builtin : BuiltinName , self_ptr : Relocatable , enter_ptr : Relocatable } ,
20
26
#[ error( "Failed to build builtin pointer map: {0}." ) ]
21
27
BuiltinPtrs ( OsHintError ) ,
22
28
#[ error( "SyscallTrace should be finalized only once." ) ]
23
29
DoubleFinalize ,
24
30
#[ error( "Failed to fetch identifier data for struct {0}." ) ]
25
31
InnerBuiltinPtrsIdentifierMissing ( String ) ,
32
+ #[ error( "{0}" ) ]
33
+ MissingBuiltinPtr ( String ) ,
26
34
#[ error( "The `members` field is None in identifier data for struct {0}." ) ]
27
35
MissingMembers ( String ) ,
36
+ #[ error(
37
+ "Range check in self and in the enter call counter are not in the same segment: \
38
+ {self_ptr}, {enter_ptr}."
39
+ ) ]
40
+ RangeCheckNotInSameSegment { self_ptr : Relocatable , enter_ptr : Relocatable } ,
28
41
#[ error( "SyscallTrace should be finalized before accessing resources." ) ]
29
42
ResourceAccessBeforeFinalize ,
30
43
#[ error( "{0}" ) ]
31
44
UnknownBuiltin ( String ) ,
45
+ #[ error( "Builtin {0} is not in the known sizes mapping {:?}." , BUILTIN_INSTANCE_SIZES ) ]
46
+ UnknownBuiltinSize ( String ) ,
32
47
}
33
48
34
49
pub type OsLoggerResult < T > = Result < T , OsLoggerError > ;
@@ -177,6 +192,49 @@ impl ResourceCounter {
177
192
} )
178
193
}
179
194
195
+ pub fn sub_counter ( & self , enter_counter : & Self ) -> OsLoggerResult < ExecutionResources > {
196
+ // Subtract pointers to count usage.
197
+ let mut builtins_count_ptr: HashMap < BuiltinName , usize > = HashMap :: new ( ) ;
198
+ for ( builtin_name, builtin_ptr) in self . builtin_ptrs_dict . iter ( ) {
199
+ let enter_counter_ptr = enter_counter
200
+ . builtin_ptrs_dict
201
+ . get ( builtin_name)
202
+ . ok_or ( OsLoggerError :: MissingBuiltinPtr ( builtin_name. to_str ( ) . to_string ( ) ) ) ?;
203
+ let mut builtin_count = ( * builtin_ptr - * enter_counter_ptr) . map_err ( |_error| {
204
+ OsLoggerError :: BuiltinsNotInSameSegment {
205
+ builtin : * builtin_name,
206
+ self_ptr : * builtin_ptr,
207
+ enter_ptr : * enter_counter_ptr,
208
+ }
209
+ } ) ?;
210
+
211
+ // Adds the OS range_check resources of the current entry point.
212
+ if builtin_name == & BuiltinName :: range_check {
213
+ builtin_count +=
214
+ ( self . range_check_ptr - enter_counter. range_check_ptr ) . map_err ( |_error| {
215
+ OsLoggerError :: RangeCheckNotInSameSegment {
216
+ self_ptr : self . range_check_ptr ,
217
+ enter_ptr : enter_counter. range_check_ptr ,
218
+ }
219
+ } ) ?;
220
+ }
221
+
222
+ // Divide by the builtin size to get the actual usage count.
223
+ let builtin_size = BUILTIN_INSTANCE_SIZES
224
+ . get ( builtin_name)
225
+ . ok_or ( OsLoggerError :: UnknownBuiltinSize ( builtin_name. to_str ( ) . to_string ( ) ) ) ?;
226
+ builtin_count /= * builtin_size;
227
+
228
+ builtins_count_ptr. insert ( * builtin_name, builtin_count) ;
229
+ }
230
+
231
+ Ok ( ExecutionResources {
232
+ n_steps : self . n_steps - enter_counter. n_steps ,
233
+ builtin_instance_counter : builtins_count_ptr,
234
+ n_memory_holes : 0 ,
235
+ } )
236
+ }
237
+
180
238
fn build_builtin_ptrs_dict (
181
239
ids_data : & HashMap < String , HintReference > ,
182
240
vm : & VirtualMachine ,
0 commit comments