Skip to content

Commit 47c140a

Browse files
Add basic cairo runner builder
1 parent fd093e7 commit 47c140a

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed

vm/src/vm/runners/cairo_runner.rs

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
144403
pub struct CairoRunner {
145404
pub vm: VirtualMachine,
146405
pub(crate) program: Program,

0 commit comments

Comments
 (0)