1
1
use std:: collections:: HashMap ;
2
+ use std:: sync:: LazyLock ;
2
3
3
4
use blockifier:: execution:: syscalls:: SyscallSelector ;
4
5
use blockifier:: transaction:: transaction_types:: TransactionType ;
@@ -15,20 +16,50 @@ 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
19
+ static BUILTIN_INSTANCE_SIZES : LazyLock < HashMap < BuiltinName , usize > > = LazyLock :: new ( || {
20
+ HashMap :: from ( [
21
+ ( BuiltinName :: pedersen, 3 ) ,
22
+ ( BuiltinName :: range_check, 1 ) ,
23
+ ( BuiltinName :: ecdsa, 2 ) ,
24
+ ( BuiltinName :: bitwise, 5 ) ,
25
+ ( BuiltinName :: ec_op, 7 ) ,
26
+ ( BuiltinName :: poseidon, 6 ) ,
27
+ ( BuiltinName :: segment_arena, 3 ) ,
28
+ ( BuiltinName :: range_check96, 1 ) ,
29
+ ( BuiltinName :: add_mod, 7 ) ,
30
+ ( BuiltinName :: mul_mod, 7 ) ,
31
+ ( BuiltinName :: keccak, 16 ) ,
32
+ ] )
33
+ } ) ;
34
+
18
35
#[ derive( Debug , thiserror:: Error ) ]
19
36
pub enum OsLoggerError {
37
+ #[ error(
38
+ "Builtin {builtin} in self and in the enter call counter are not in the same segment: \
39
+ {self_ptr}, {enter_ptr}."
40
+ ) ]
41
+ BuiltinsNotInSameSegment { builtin : BuiltinName , self_ptr : Relocatable , enter_ptr : Relocatable } ,
20
42
#[ error( "Failed to build builtin pointer map: {0}." ) ]
21
43
BuiltinPtrs ( OsHintError ) ,
22
44
#[ error( "SyscallTrace should be finalized only once." ) ]
23
45
DoubleFinalize ,
24
46
#[ error( "Failed to fetch identifier data for struct {0}." ) ]
25
47
InnerBuiltinPtrsIdentifierMissing ( String ) ,
48
+ #[ error( "{0}" ) ]
49
+ MissingBuiltinPtr ( String ) ,
26
50
#[ error( "The `members` field is None in identifier data for struct {0}." ) ]
27
51
MissingMembers ( String ) ,
52
+ #[ error(
53
+ "Range check in self and in the enter call counter are not in the same segment: \
54
+ {self_ptr}, {enter_ptr}."
55
+ ) ]
56
+ RangeCheckNotInSameSegment { self_ptr : Relocatable , enter_ptr : Relocatable } ,
28
57
#[ error( "SyscallTrace should be finalized before accessing resources." ) ]
29
58
ResourceAccessBeforeFinalize ,
30
59
#[ error( "{0}" ) ]
31
60
UnknownBuiltin ( String ) ,
61
+ #[ error( "Builtin {0} is not in the known sizes mapping {:?}." , BUILTIN_INSTANCE_SIZES ) ]
62
+ UnknownBuiltinSize ( String ) ,
32
63
}
33
64
34
65
pub type OsLoggerResult < T > = Result < T , OsLoggerError > ;
@@ -177,6 +208,49 @@ impl ResourceCounter {
177
208
} )
178
209
}
179
210
211
+ pub fn sub_counter ( & self , enter_counter : & Self ) -> OsLoggerResult < ExecutionResources > {
212
+ // Subtract pointers to count usage.
213
+ let mut builtins_count_ptr: HashMap < BuiltinName , usize > = HashMap :: new ( ) ;
214
+ for ( builtin_name, builtin_ptr) in self . builtin_ptrs_dict . iter ( ) {
215
+ let enter_counter_ptr = enter_counter
216
+ . builtin_ptrs_dict
217
+ . get ( builtin_name)
218
+ . ok_or ( OsLoggerError :: MissingBuiltinPtr ( builtin_name. to_str ( ) . to_string ( ) ) ) ?;
219
+ let mut builtin_count = ( * builtin_ptr - * enter_counter_ptr) . map_err ( |_error| {
220
+ OsLoggerError :: BuiltinsNotInSameSegment {
221
+ builtin : * builtin_name,
222
+ self_ptr : * builtin_ptr,
223
+ enter_ptr : * enter_counter_ptr,
224
+ }
225
+ } ) ?;
226
+
227
+ // For range check, also add the specific pointer field offset.
228
+ if builtin_name == & BuiltinName :: range_check {
229
+ builtin_count +=
230
+ ( self . range_check_ptr - enter_counter. range_check_ptr ) . map_err ( |_error| {
231
+ OsLoggerError :: RangeCheckNotInSameSegment {
232
+ self_ptr : self . range_check_ptr ,
233
+ enter_ptr : enter_counter. range_check_ptr ,
234
+ }
235
+ } ) ?;
236
+ }
237
+
238
+ // Divide by the builtin size to get the actual usage count.
239
+ let builtin_size = BUILTIN_INSTANCE_SIZES
240
+ . get ( builtin_name)
241
+ . ok_or ( OsLoggerError :: UnknownBuiltinSize ( builtin_name. to_str ( ) . to_string ( ) ) ) ?;
242
+ builtin_count /= * builtin_size;
243
+
244
+ builtins_count_ptr. insert ( * builtin_name, builtin_count) ;
245
+ }
246
+
247
+ Ok ( ExecutionResources {
248
+ n_steps : self . n_steps - enter_counter. n_steps ,
249
+ builtin_instance_counter : builtins_count_ptr,
250
+ n_memory_holes : 0 ,
251
+ } )
252
+ }
253
+
180
254
fn build_builtin_ptrs_dict (
181
255
ids_data : & HashMap < String , HintReference > ,
182
256
vm : & VirtualMachine ,
0 commit comments