2
2
3
3
use core:: any:: Any ;
4
4
5
- use cairo_lang_executable:: executable:: { EntryPointKind , Executable , ExecutableEntryPoint } ;
6
-
7
5
use crate :: {
8
6
hint_processor:: hint_processor_definition:: { HintProcessor , HintReference } ,
9
- serde:: deserialize_program:: { Attribute , HintParams , Identifier , InstructionLocation } ,
7
+ serde:: deserialize_program:: HintParams ,
10
8
stdlib:: {
11
9
collections:: { BTreeMap , HashMap , HashSet } ,
12
- mem,
13
10
prelude:: * ,
14
11
} ,
15
12
types:: {
16
13
builtin_name:: BuiltinName ,
14
+ errors:: program_errors:: ProgramError ,
17
15
exec_scope:: ExecutionScopes ,
18
16
layout:: CairoLayout ,
19
17
program:: HintsCollection ,
@@ -34,6 +32,52 @@ use crate::{
34
32
Felt252 ,
35
33
} ;
36
34
35
+ /// This type is originally defined in `cairo-lang-executable`.
36
+ /// We redefine it here to avoid a cyclic dependencies.
37
+ #[ derive( Debug ) ]
38
+ pub struct ExecutableEntryPoint {
39
+ pub builtins : Vec < BuiltinName > ,
40
+ pub offset : usize ,
41
+ pub kind : EntryPointKind ,
42
+ }
43
+
44
+ /// This type is originally defined in `cairo-lang-executable`.
45
+ /// We redefine it here to avoid a cyclic dependencies.
46
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
47
+ pub enum EntryPointKind {
48
+ Bootloader ,
49
+ Standalone ,
50
+ }
51
+
52
+ pub struct Program2 {
53
+ pub bytecode : Vec < MaybeRelocatable > ,
54
+ pub hints_collection : HintsCollection ,
55
+ pub entrypoint : ExecutableEntryPoint ,
56
+
57
+ pub reference_manager : Vec < HintReference > ,
58
+ pub constants : HashMap < String , Felt252 > ,
59
+ }
60
+
61
+ impl Program2 {
62
+ pub fn new (
63
+ bytecode : Vec < MaybeRelocatable > ,
64
+ hints : BTreeMap < usize , Vec < HintParams > > ,
65
+ entrypoint : ExecutableEntryPoint ,
66
+ reference_manager : Vec < HintReference > ,
67
+ constants : HashMap < String , Felt252 > ,
68
+ ) -> Result < Program2 , ProgramError > {
69
+ let hints_collection = HintsCollection :: new ( & hints, bytecode. len ( ) ) ?;
70
+
71
+ Ok ( Self {
72
+ bytecode,
73
+ hints_collection,
74
+ entrypoint,
75
+ reference_manager,
76
+ constants,
77
+ } )
78
+ }
79
+ }
80
+
37
81
#[ allow( dead_code) ]
38
82
pub struct CairoRunner2 {
39
83
vm : VirtualMachine ,
@@ -43,74 +87,39 @@ pub struct CairoRunner2 {
43
87
execution_scopes : ExecutionScopes ,
44
88
45
89
// Configuration
46
- executable : Executable ,
47
- entrypoint_kind : EntryPointKind ,
90
+ program : Program2 ,
48
91
layout : CairoLayout ,
49
- trace_enabled : bool ,
50
- constants : HashMap < String , Felt252 > ,
51
- error_message_attributes : Vec < Attribute > ,
52
- instruction_locations : Option < HashMap < usize , InstructionLocation > > ,
53
- identifiers : HashMap < String , Identifier > ,
54
- reference_manager : Vec < HintReference > ,
55
-
56
- // Preprocessed Data
57
- hint_collection : HintsCollection ,
58
92
}
59
93
60
94
impl CairoRunner2 {
61
95
#[ allow( clippy:: too_many_arguments) ]
62
96
pub fn new (
63
- executable : Executable ,
64
- entrypoint_kind : EntryPointKind ,
97
+ program : Program2 ,
65
98
layout : CairoLayout ,
66
99
trace_enabled : bool ,
67
- constants : HashMap < String , Felt252 > ,
68
- error_message_attributes : Vec < Attribute > ,
69
- instruction_locations : Option < HashMap < usize , InstructionLocation > > ,
70
- identifiers : HashMap < String , Identifier > ,
71
- reference_manager : Vec < HintReference > ,
72
- hints : BTreeMap < usize , Vec < HintParams > > ,
73
100
) -> Result < Self , RunnerError > {
74
- // =============
75
- // PREPROCESSING
76
- // =============
77
-
78
- let entrypoint = find_entrypoint_of_kind ( & executable. entrypoints , entrypoint_kind. clone ( ) ) ;
79
-
80
- let bytecode = executable
81
- . program
82
- . bytecode
83
- . iter ( )
84
- . map ( Felt252 :: from)
85
- . map ( MaybeRelocatable :: from)
86
- . collect :: < Vec < _ > > ( ) ;
87
-
88
- let hint_collection =
89
- HintsCollection :: new ( & hints, bytecode. len ( ) ) . expect ( "failed to build hint collection" ) ;
90
-
91
- let builtins = get_entrypoint_builtins ( entrypoint) ;
92
-
93
101
// ==============
94
102
// INITIALIZATION
95
103
// ==============
96
104
97
105
let mut vm = VirtualMachine :: new ( trace_enabled, false ) ;
98
106
99
- check_builtin_order ( & builtins) ?;
100
- vm. builtin_runners = initialize_builtin_runners ( & layout, & builtins, true , true ) ?;
107
+ check_builtin_order ( & ( & program. entrypoint ) . builtins ) ?;
108
+ vm. builtin_runners =
109
+ initialize_builtin_runners ( & layout, & program. entrypoint . builtins , true , true ) ?;
101
110
102
111
let program_base = vm. add_memory_segment ( ) ;
103
112
let execution_base = vm. add_memory_segment ( ) ;
104
113
105
114
initialize_builtin_runner_segments ( & mut vm. builtin_runners , & mut vm. segments ) ;
106
115
107
- load_program ( & mut vm, program_base, & bytecode) ?;
116
+ load_program ( & mut vm, program_base, & program . bytecode ) ?;
108
117
109
118
let mut stack = Vec :: new ( ) ;
110
119
111
- let initial_pc = ( program_base + entrypoint. offset ) ?;
120
+ let initial_pc = ( program_base + ( & program . entrypoint ) . offset ) ?;
112
121
113
- let ( initial_fp, final_pc) = match entrypoint_kind {
122
+ let ( initial_fp, final_pc) = match ( & program . entrypoint ) . kind {
114
123
EntryPointKind :: Bootloader => {
115
124
// On bootloader, we execute until control flow is returned.
116
125
// The stack is arranged as if we are at the start of a function call.
@@ -125,7 +134,11 @@ impl CairoRunner2 {
125
134
//
126
135
// The initial fp variable points to the cell after the return pc.
127
136
128
- extend_stack_with_builtins ( & mut stack, & builtins, & vm. builtin_runners ) ;
137
+ extend_stack_with_builtins (
138
+ & mut stack,
139
+ & program. entrypoint . builtins ,
140
+ & vm. builtin_runners ,
141
+ ) ;
129
142
130
143
let return_fp = vm. add_memory_segment ( ) ;
131
144
let return_pc = vm. add_memory_segment ( ) ;
@@ -154,7 +167,11 @@ impl CairoRunner2 {
154
167
155
168
let stack_prefix = & [ MaybeRelocatable :: Int ( Felt252 :: ZERO ) ] ;
156
169
stack. extend_from_slice ( stack_prefix) ;
157
- extend_stack_with_builtins ( & mut stack, & builtins, & vm. builtin_runners ) ;
170
+ extend_stack_with_builtins (
171
+ & mut stack,
172
+ & program. entrypoint . builtins ,
173
+ & vm. builtin_runners ,
174
+ ) ;
158
175
159
176
let final_pc = ( initial_pc + 4 ) ?;
160
177
let initial_fp = ( execution_base + stack_prefix. len ( ) ) ?;
@@ -172,21 +189,13 @@ impl CairoRunner2 {
172
189
add_builtin_validation_rules ( & mut vm. segments . memory , & mut vm. builtin_runners ) ?;
173
190
174
191
Ok ( Self {
175
- executable,
176
192
vm,
177
193
program_base,
178
194
execution_base,
179
195
final_pc,
180
196
execution_scopes : ExecutionScopes :: new ( ) ,
181
- entrypoint_kind ,
197
+ program ,
182
198
layout,
183
- trace_enabled,
184
- constants,
185
- error_message_attributes,
186
- instruction_locations,
187
- identifiers,
188
- reference_manager,
189
- hint_collection,
190
199
} )
191
200
}
192
201
@@ -196,20 +205,21 @@ impl CairoRunner2 {
196
205
) -> Result < ( ) , VirtualMachineError > {
197
206
#[ cfg_attr( not( feature = "extensive_hints" ) , allow( unused_mut) ) ]
198
207
let mut hint_data = get_hint_data (
199
- & self . hint_collection ,
200
- & self . reference_manager ,
208
+ & self . program . hints_collection ,
209
+ & self . program . reference_manager ,
201
210
hint_processor,
202
211
) ?;
203
212
204
213
#[ cfg( feature = "extensive_hints" ) ]
205
- let mut hint_ranges = self . hint_collection . hints_ranges . clone ( ) ;
214
+ let mut hint_ranges = self . program . hints_collection . hints_ranges . clone ( ) ;
206
215
207
216
while self . vm . get_pc ( ) != self . final_pc && !hint_processor. consumed ( ) {
208
217
#[ cfg( feature = "extensive_hints" ) ]
209
218
let hint_data = & mut hint_data;
210
219
#[ cfg( not( feature = "extensive_hints" ) ) ]
211
220
let hint_data = self
212
- . hint_collection
221
+ . program
222
+ . hints_collection
213
223
. get_hint_range_for_pc ( self . vm . get_pc ( ) . offset )
214
224
. and_then ( |range| {
215
225
range. and_then ( |( start, length) | hint_data. get ( start..start + length. get ( ) ) )
@@ -222,7 +232,7 @@ impl CairoRunner2 {
222
232
hint_data,
223
233
#[ cfg( feature = "extensive_hints" ) ]
224
234
& mut hint_ranges,
225
- & self . constants ,
235
+ & self . program . constants ,
226
236
) ?;
227
237
228
238
hint_processor. consume_step ( ) ;
@@ -236,19 +246,6 @@ impl CairoRunner2 {
236
246
}
237
247
}
238
248
239
- fn find_entrypoint_of_kind (
240
- entrypoints : & [ ExecutableEntryPoint ] ,
241
- entrypoint_kind : EntryPointKind ,
242
- ) -> & ExecutableEntryPoint {
243
- entrypoints
244
- . iter ( )
245
- . find ( |entrypoint| {
246
- // TODO: Use `Eq` once implemented on `EntryPointKind`.
247
- mem:: discriminant ( & entrypoint. kind ) == mem:: discriminant ( & entrypoint_kind)
248
- } )
249
- . expect ( "executable had no entrypoint of required kind" )
250
- }
251
-
252
249
pub fn check_builtin_order ( builtins : & [ BuiltinName ] ) -> Result < ( ) , RunnerError > {
253
250
let ordered_builtins = vec ! [
254
251
BuiltinName :: output,
@@ -465,18 +462,3 @@ fn get_hint_data(
465
462
} )
466
463
. collect ( )
467
464
}
468
-
469
- /// TODO: Remove this once cyclic dependency is fixed.
470
- /// It should not be necessary, but cargo treats executable BuiltinName as a separate type
471
- /// which is why I had to create this adapter function.
472
- pub fn get_entrypoint_builtins ( entrypoint : & ExecutableEntryPoint ) -> Vec < BuiltinName > {
473
- let mut builtins = Vec :: with_capacity ( entrypoint. builtins . len ( ) ) ;
474
-
475
- for builtin in & entrypoint. builtins {
476
- let adapted_builtin = BuiltinName :: from_str ( builtin. to_str ( ) )
477
- . expect ( "should never fail under the same implementation" ) ;
478
- builtins. push ( adapted_builtin) ;
479
- }
480
-
481
- builtins
482
- }
0 commit comments