@@ -13,6 +13,7 @@ use crate::{
1313 vm:: {
1414 runners:: builtin_runner:: SegmentArenaBuiltinRunner ,
1515 trace:: trace_entry:: { relocate_trace_register, RelocatedTraceEntry , TraceEntry } ,
16+ vm_memory:: memory_segments:: MemorySegmentManager ,
1617 } ,
1718 Felt252 ,
1819} ;
@@ -141,6 +142,264 @@ impl ResourceTracker for RunResources {
141142 }
142143}
143144
145+ #[ derive( Clone ) ]
146+ pub struct CairoRunnerBuilder {
147+ program : Program ,
148+ layout : CairoLayout ,
149+ runner_mode : RunnerMode ,
150+ // Flags.
151+ enable_trace : bool ,
152+ disable_trace_padding : bool ,
153+ allow_missing_builtins : bool ,
154+ // Set after initializing builtin runners.
155+ builtin_runners : Vec < BuiltinRunner > ,
156+ // Set after initializing segments.
157+ program_base : Option < Relocatable > ,
158+ execution_base : Option < Relocatable > ,
159+ memory : MemorySegmentManager ,
160+ // Set after loading instruction cache.
161+ // instructions: Vec<Option<Instruction>>,
162+ // Set after compiling hints.
163+ // hints: Vec<Rc<dyn Any>>,
164+ }
165+
166+ impl CairoRunnerBuilder {
167+ pub fn new (
168+ program : & Program ,
169+ layout_name : LayoutName ,
170+ dynamic_layout_params : Option < CairoLayoutParams > ,
171+ runner_mode : RunnerMode ,
172+ ) -> Result < CairoRunnerBuilder , RunnerError > {
173+ let layout = match layout_name {
174+ LayoutName :: plain => CairoLayout :: plain_instance ( ) ,
175+ LayoutName :: small => CairoLayout :: small_instance ( ) ,
176+ LayoutName :: dex => CairoLayout :: dex_instance ( ) ,
177+ LayoutName :: recursive => CairoLayout :: recursive_instance ( ) ,
178+ LayoutName :: starknet => CairoLayout :: starknet_instance ( ) ,
179+ LayoutName :: starknet_with_keccak => CairoLayout :: starknet_with_keccak_instance ( ) ,
180+ LayoutName :: recursive_large_output => CairoLayout :: recursive_large_output_instance ( ) ,
181+ LayoutName :: recursive_with_poseidon => CairoLayout :: recursive_with_poseidon ( ) ,
182+ LayoutName :: all_cairo => CairoLayout :: all_cairo_instance ( ) ,
183+ LayoutName :: all_cairo_stwo => CairoLayout :: all_cairo_stwo_instance ( ) ,
184+ LayoutName :: all_solidity => CairoLayout :: all_solidity_instance ( ) ,
185+ LayoutName :: dynamic => {
186+ let params =
187+ dynamic_layout_params. ok_or ( RunnerError :: MissingDynamicLayoutParams ) ?;
188+ CairoLayout :: dynamic_instance ( params)
189+ }
190+ } ;
191+
192+ Ok ( CairoRunnerBuilder {
193+ program : program. clone ( ) ,
194+ layout,
195+ enable_trace : false ,
196+ disable_trace_padding : false ,
197+ allow_missing_builtins : false ,
198+ runner_mode,
199+ builtin_runners : Vec :: new ( ) ,
200+ program_base : None ,
201+ execution_base : None ,
202+ memory : MemorySegmentManager :: new ( ) ,
203+ } )
204+ }
205+
206+ pub fn enable_trace ( & mut self , v : bool ) {
207+ self . enable_trace = v;
208+ }
209+ pub fn disable_trace_padding ( & mut self , v : bool ) {
210+ self . disable_trace_padding = v;
211+ }
212+ pub fn allow_missing_builtins ( & mut self , v : bool ) {
213+ self . allow_missing_builtins = v;
214+ }
215+
216+ fn is_proof_mode ( & self ) -> bool {
217+ self . runner_mode == RunnerMode :: ProofModeCanonical
218+ || self . runner_mode == RunnerMode :: ProofModeCairo1
219+ }
220+
221+ fn add_memory_segment ( & mut self ) -> Relocatable {
222+ self . memory . add ( )
223+ }
224+
225+ pub fn initialize_builtin_runners_for_layout ( & mut self ) -> Result < ( ) , RunnerError > {
226+ let builtin_ordered_list = vec ! [
227+ BuiltinName :: output,
228+ BuiltinName :: pedersen,
229+ BuiltinName :: range_check,
230+ BuiltinName :: ecdsa,
231+ BuiltinName :: bitwise,
232+ BuiltinName :: ec_op,
233+ BuiltinName :: keccak,
234+ BuiltinName :: poseidon,
235+ BuiltinName :: range_check96,
236+ BuiltinName :: add_mod,
237+ BuiltinName :: mul_mod,
238+ ] ;
239+ if !is_subsequence ( & self . program . builtins , & builtin_ordered_list) {
240+ return Err ( RunnerError :: DisorderedBuiltins ) ;
241+ } ;
242+ let mut program_builtins: HashSet < & BuiltinName > = self . program . builtins . iter ( ) . collect ( ) ;
243+
244+ if self . layout . builtins . output {
245+ let included = program_builtins. remove ( & BuiltinName :: output) ;
246+ if included || self . is_proof_mode ( ) {
247+ self . builtin_runners
248+ . push ( OutputBuiltinRunner :: new ( included) . into ( ) ) ;
249+ }
250+ }
251+
252+ if let Some ( instance_def) = self . layout . builtins . pedersen . as_ref ( ) {
253+ let included = program_builtins. remove ( & BuiltinName :: pedersen) ;
254+ if included || self . is_proof_mode ( ) {
255+ self . builtin_runners
256+ . push ( HashBuiltinRunner :: new ( instance_def. ratio , included) . into ( ) ) ;
257+ }
258+ }
259+
260+ if let Some ( instance_def) = self . layout . builtins . range_check . as_ref ( ) {
261+ let included = program_builtins. remove ( & BuiltinName :: range_check) ;
262+ if included || self . is_proof_mode ( ) {
263+ self . builtin_runners . push (
264+ RangeCheckBuiltinRunner :: < RC_N_PARTS_STANDARD > :: new_with_low_ratio (
265+ instance_def. ratio ,
266+ included,
267+ )
268+ . into ( ) ,
269+ ) ;
270+ }
271+ }
272+
273+ if let Some ( instance_def) = self . layout . builtins . ecdsa . as_ref ( ) {
274+ let included = program_builtins. remove ( & BuiltinName :: ecdsa) ;
275+ if included || self . is_proof_mode ( ) {
276+ self . builtin_runners
277+ . push ( SignatureBuiltinRunner :: new ( instance_def. ratio , included) . into ( ) ) ;
278+ }
279+ }
280+
281+ if let Some ( instance_def) = self . layout . builtins . bitwise . as_ref ( ) {
282+ let included = program_builtins. remove ( & BuiltinName :: bitwise) ;
283+ if included || self . is_proof_mode ( ) {
284+ self . builtin_runners
285+ . push ( BitwiseBuiltinRunner :: new ( instance_def. ratio , included) . into ( ) ) ;
286+ }
287+ }
288+
289+ if let Some ( instance_def) = self . layout . builtins . ec_op . as_ref ( ) {
290+ let included = program_builtins. remove ( & BuiltinName :: ec_op) ;
291+ if included || self . is_proof_mode ( ) {
292+ self . builtin_runners
293+ . push ( EcOpBuiltinRunner :: new ( instance_def. ratio , included) . into ( ) ) ;
294+ }
295+ }
296+
297+ if let Some ( instance_def) = self . layout . builtins . keccak . as_ref ( ) {
298+ let included = program_builtins. remove ( & BuiltinName :: keccak) ;
299+ if included || self . is_proof_mode ( ) {
300+ self . builtin_runners
301+ . push ( KeccakBuiltinRunner :: new ( instance_def. ratio , included) . into ( ) ) ;
302+ }
303+ }
304+
305+ if let Some ( instance_def) = self . layout . builtins . poseidon . as_ref ( ) {
306+ let included = program_builtins. remove ( & BuiltinName :: poseidon) ;
307+ if included || self . is_proof_mode ( ) {
308+ self . builtin_runners
309+ . push ( PoseidonBuiltinRunner :: new ( instance_def. ratio , included) . into ( ) ) ;
310+ }
311+ }
312+
313+ if let Some ( instance_def) = self . layout . builtins . range_check96 . as_ref ( ) {
314+ let included = program_builtins. remove ( & BuiltinName :: range_check96) ;
315+ if included || self . is_proof_mode ( ) {
316+ self . builtin_runners . push (
317+ RangeCheckBuiltinRunner :: < RC_N_PARTS_96 > :: new_with_low_ratio (
318+ instance_def. ratio ,
319+ included,
320+ )
321+ . into ( ) ,
322+ ) ;
323+ }
324+ }
325+
326+ if let Some ( instance_def) = self . layout . builtins . add_mod . as_ref ( ) {
327+ let included = program_builtins. remove ( & BuiltinName :: add_mod) ;
328+ if included || self . is_proof_mode ( ) {
329+ self . builtin_runners
330+ . push ( ModBuiltinRunner :: new_add_mod ( instance_def, included) . into ( ) ) ;
331+ }
332+ }
333+
334+ if let Some ( instance_def) = self . layout . builtins . mul_mod . as_ref ( ) {
335+ let included = program_builtins. remove ( & BuiltinName :: mul_mod) ;
336+ if included || self . is_proof_mode ( ) {
337+ self . builtin_runners
338+ . push ( ModBuiltinRunner :: new_mul_mod ( instance_def, included) . into ( ) ) ;
339+ }
340+ }
341+
342+ if !program_builtins. is_empty ( ) && !self . allow_missing_builtins {
343+ return Err ( RunnerError :: NoBuiltinForInstance ( Box :: new ( (
344+ program_builtins. iter ( ) . map ( |n| * * n) . collect ( ) ,
345+ self . layout . name ,
346+ ) ) ) ) ;
347+ }
348+
349+ Ok ( ( ) )
350+ }
351+
352+ pub fn initialize_segments ( & mut self ) {
353+ self . program_base = Some ( self . add_memory_segment ( ) ) ;
354+ self . execution_base = Some ( self . add_memory_segment ( ) ) ;
355+ for builtin_runner in self . builtin_runners . iter_mut ( ) {
356+ builtin_runner. initialize_segments ( & mut self . memory ) ;
357+ }
358+ }
359+
360+ pub fn load_program ( & mut self ) -> Result < ( ) , RunnerError > {
361+ let program_base = self . program_base . ok_or ( RunnerError :: NoProgBase ) ?;
362+ self . memory
363+ . load_data ( program_base, & self . program . shared_program_data . data )
364+ . map_err ( RunnerError :: MemoryInitializationError ) ?;
365+ for i in 0 ..self . program . shared_program_data . data . len ( ) {
366+ self . memory . memory . mark_as_accessed ( ( program_base + i) ?) ;
367+ }
368+ Ok ( ( ) )
369+ }
370+
371+ pub fn build ( self ) -> Result < CairoRunner , RunnerError > {
372+ let mut vm = VirtualMachine :: new ( self . enable_trace , self . disable_trace_padding ) ;
373+
374+ vm. builtin_runners = self . builtin_runners ;
375+ vm. segments = self . memory ;
376+
377+ Ok ( CairoRunner {
378+ vm,
379+ layout : self . layout ,
380+ program_base : self . program_base ,
381+ execution_base : self . execution_base ,
382+ entrypoint : self . program . shared_program_data . main ,
383+ initial_ap : None ,
384+ initial_fp : None ,
385+ initial_pc : None ,
386+ final_pc : None ,
387+ run_ended : false ,
388+ segments_finalized : false ,
389+ execution_public_memory : if self . runner_mode != RunnerMode :: ExecutionMode {
390+ Some ( Vec :: new ( ) )
391+ } else {
392+ None
393+ } ,
394+ runner_mode : self . runner_mode ,
395+ relocated_memory : Vec :: new ( ) ,
396+ exec_scopes : ExecutionScopes :: new ( ) ,
397+ relocated_trace : None ,
398+ program : self . program ,
399+ } )
400+ }
401+ }
402+
144403pub struct CairoRunner {
145404 pub vm : VirtualMachine ,
146405 pub ( crate ) program : Program ,
0 commit comments