Skip to content

Commit 46ad0b8

Browse files
mmsc2pefontana
andauthored
Implement run resources funcs (#1175)
* Add RunResources structure * Modify changelog * change data type of n_steps from u64 to usize * Implement run resources functions * Fix tests * set comment about calculation in cairo_run * Change CHangelog and remove option from RunResources * Fix clippy * Add clone trait to run resources * Add debug and default traits to RunResources * Fix error in while loop inside run_until_pc * Add helper function for clarity in run_until_pc loop * Add test for cairo 0 contracts * Add tests with Cairo 1 contracts * Move RunResources struct to vm::runners::cairo_runner::RunResources * Update CHANGELOG.md * Fix wasm and no-std compilation --------- Co-authored-by: Pedro Fontana <[email protected]>
1 parent 02f3c55 commit 46ad0b8

File tree

16 files changed

+399
-49
lines changed

16 files changed

+399
-49
lines changed

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616

1717
* fix: Handle the deserialization of serde_json::Number with scientific notation (e.g.: Number(1e27)) in felt_from_number function [#1188](https://github.com/lambdaclass/cairo-rs/pull/1188)
1818

19+
* feat: Add RunResources Struct [#1175](https://github.com/lambdaclass/cairo-rs/pull/1175)
20+
* BREAKING: Modify `CairoRunner::run_until_pc` arity. Add `run_resources: &mut Option<RunResources>` input
21+
* BREAKING: Modify `CairoRunner::run_from_entrypoint` arity. Add `run_resources: &mut Option<RunResources>` input
22+
1923
* fix: Fix 'as_int' conversion usage in hints `ASSERT_250_BIT` & `SIGNED_DIV_REM` [#1191](https://github.com/lambdaclass/cairo-rs/pull/1191)
2024

21-
* fix: Fix hint `BIGINT_PACK_DIV_MOD` [#1189](https://github.com/lambdaclass/cairo-rs/pull/1189)
2225

2326
* bugfix: Use cairo constants in `ASSERT_250_BIT` hint [#1187](https://github.com/lambdaclass/cairo-rs/pull/1187)
2427

src/cairo_run.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@ pub fn cairo_run(
5555
cairo_run_config.layout,
5656
cairo_run_config.proof_mode,
5757
)?;
58+
5859
let mut vm = VirtualMachine::new(cairo_run_config.trace_enabled);
5960
let end = cairo_runner.initialize(&mut vm)?;
61+
// check step calculation
62+
let mut run_resources = None;
6063

6164
cairo_runner
62-
.run_until_pc(end, &mut vm, hint_executor)
65+
.run_until_pc(end, &mut run_resources, &mut vm, hint_executor)
6366
.map_err(|err| VmException::from_vm_error(&cairo_runner, &vm, err))?;
6467
cairo_runner.end_run(false, false, &mut vm, hint_executor)?;
6568

@@ -153,7 +156,7 @@ mod tests {
153156
.map_err(CairoRunError::Runner)?;
154157

155158
assert!(cairo_runner
156-
.run_until_pc(end, &mut vm, hint_processor)
159+
.run_until_pc(end, &mut None, &mut vm, hint_processor)
157160
.is_ok());
158161

159162
Ok((cairo_runner, vm))
@@ -173,7 +176,7 @@ mod tests {
173176

174177
let end = cairo_runner.initialize(&mut vm).unwrap();
175178
assert!(cairo_runner
176-
.run_until_pc(end, &mut vm, &mut hint_processor)
179+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
177180
.is_ok());
178181
assert!(cairo_runner.relocate(&mut vm, true).is_ok());
179182
// `main` returns without doing nothing, but `not_main` sets `[ap]` to `1`
@@ -293,7 +296,7 @@ mod tests {
293296
let mut vm = vm!();
294297
let end = cairo_runner.initialize(&mut vm).unwrap();
295298
assert!(cairo_runner
296-
.run_until_pc(end, &mut vm, &mut hint_processor)
299+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
297300
.is_ok());
298301
assert!(cairo_runner.relocate(&mut vm, false).is_ok());
299302
assert!(vm.get_relocated_trace().is_err());

src/tests/cairo_1_run_from_entrypoint_tests.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::tests::*;
2+
use assert_matches::assert_matches;
23

34
#[test]
45
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
@@ -558,3 +559,60 @@ fn uint512_div_mod_test() {
558559
&[],
559560
);
560561
}
562+
563+
// ================
564+
// Tests run cairo 1 entrypoint with RunResources
565+
// ================
566+
567+
#[test]
568+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
569+
fn fibonacci_with_run_resources_ok() {
570+
let program_data = include_bytes!("../../cairo_programs/cairo-1-contracts/fib.casm");
571+
let mut resources = Some(RunResources::new(621));
572+
// Program takes 621 steps
573+
assert_matches!(
574+
run_cairo_1_entrypoint_with_run_resources(
575+
program_data.as_slice(),
576+
0,
577+
&mut resources,
578+
&[1_usize.into(), 1_usize.into(), 20_usize.into()],
579+
),
580+
Ok(x) if x == [10946_usize.into()]
581+
);
582+
583+
assert_eq!(resources, Some(RunResources::new(0)));
584+
}
585+
586+
#[test]
587+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
588+
fn fibonacci_with_run_resources_2_ok() {
589+
let program_data = include_bytes!("../../cairo_programs/cairo-1-contracts/fib.casm");
590+
let mut resources = Some(RunResources::new(1000));
591+
// Program takes 621 steps
592+
assert_matches!(
593+
run_cairo_1_entrypoint_with_run_resources(
594+
program_data.as_slice(),
595+
0,
596+
&mut resources,
597+
&[1_usize.into(), 1_usize.into(), 20_usize.into()],
598+
),
599+
Ok(x) if x == [10946_usize.into()]
600+
);
601+
assert_eq!(resources, Some(RunResources::new(1000 - 621)));
602+
}
603+
604+
#[test]
605+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
606+
fn fibonacci_with_run_resources_error() {
607+
let program_data = include_bytes!("../../cairo_programs/cairo-1-contracts/fib.casm");
608+
let mut resources = Some(RunResources::new(100));
609+
// Program takes 621 steps
610+
assert!(run_cairo_1_entrypoint_with_run_resources(
611+
program_data.as_slice(),
612+
0,
613+
&mut resources,
614+
&[1_usize.into(), 1_usize.into(), 20_usize.into()],
615+
)
616+
.is_err());
617+
assert_eq!(resources, Some(RunResources::new(0)));
618+
}

src/tests/mod.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
#[cfg(feature = "cairo-1-hints")]
2+
use crate::vm::errors::cairo_run_errors::CairoRunError;
3+
#[cfg(feature = "cairo-1-hints")]
4+
use crate::vm::runners::cairo_runner::RunResources;
5+
#[cfg(feature = "cairo-1-hints")]
26
use crate::{
37
hint_processor::cairo_1_hint_processor::hint_processor::Cairo1HintProcessor,
48
serde::deserialize_program::BuiltinName,
@@ -186,6 +190,7 @@ pub(self) fn run_cairo_1_entrypoint(
186190
.run_from_entrypoint(
187191
entrypoint_offset,
188192
&entrypoint_args,
193+
&mut None,
189194
true,
190195
Some(runner.program.shared_program_data.data.len() + program_extra_data.len()),
191196
&mut vm,
@@ -206,6 +211,110 @@ pub(self) fn run_cairo_1_entrypoint(
206211
assert_eq!(expected_retdata, &retdata);
207212
}
208213

214+
#[cfg(feature = "cairo-1-hints")]
215+
/// Equals to fn run_cairo_1_entrypoint
216+
/// But with run_resources as an input
217+
pub(self) fn run_cairo_1_entrypoint_with_run_resources(
218+
program_content: &[u8],
219+
entrypoint_offset: usize,
220+
run_resources: &mut Option<RunResources>,
221+
args: &[MaybeRelocatable],
222+
) -> Result<Vec<Felt252>, CairoRunError> {
223+
let contract_class: CasmContractClass = serde_json::from_slice(program_content).unwrap();
224+
let mut hint_processor = Cairo1HintProcessor::new(&contract_class.hints);
225+
226+
let mut runner = CairoRunner::new(
227+
&(contract_class.clone().try_into().unwrap()),
228+
"all_cairo",
229+
false,
230+
)
231+
.unwrap();
232+
let mut vm = VirtualMachine::new(false);
233+
234+
let program_builtins = get_casm_contract_builtins(&contract_class, entrypoint_offset);
235+
runner
236+
.initialize_function_runner_cairo_1(&mut vm, &program_builtins)
237+
.unwrap();
238+
239+
// Implicit Args
240+
let syscall_segment = MaybeRelocatable::from(vm.add_memory_segment());
241+
242+
let builtins: Vec<&'static str> = runner
243+
.get_program_builtins()
244+
.iter()
245+
.map(|b| b.name())
246+
.collect();
247+
248+
let builtin_segment: Vec<MaybeRelocatable> = vm
249+
.get_builtin_runners()
250+
.iter()
251+
.filter(|b| builtins.contains(&b.name()))
252+
.flat_map(|b| b.initial_stack())
253+
.collect();
254+
255+
let initial_gas = MaybeRelocatable::from(usize::MAX);
256+
257+
let mut implicit_args = builtin_segment;
258+
implicit_args.extend([initial_gas]);
259+
implicit_args.extend([syscall_segment]);
260+
261+
// Other args
262+
263+
// Load builtin costs
264+
let builtin_costs: Vec<MaybeRelocatable> =
265+
vec![0.into(), 0.into(), 0.into(), 0.into(), 0.into()];
266+
let builtin_costs_ptr = vm.add_memory_segment();
267+
vm.load_data(builtin_costs_ptr, &builtin_costs).unwrap();
268+
269+
// Load extra data
270+
let core_program_end_ptr =
271+
(runner.program_base.unwrap() + runner.program.shared_program_data.data.len()).unwrap();
272+
let program_extra_data: Vec<MaybeRelocatable> =
273+
vec![0x208B7FFF7FFF7FFE.into(), builtin_costs_ptr.into()];
274+
vm.load_data(core_program_end_ptr, &program_extra_data)
275+
.unwrap();
276+
277+
// Load calldata
278+
let calldata_start = vm.add_memory_segment();
279+
let calldata_end = vm.load_data(calldata_start, &args.to_vec()).unwrap();
280+
281+
// Create entrypoint_args
282+
283+
let mut entrypoint_args: Vec<CairoArg> = implicit_args
284+
.iter()
285+
.map(|m| CairoArg::from(m.clone()))
286+
.collect();
287+
entrypoint_args.extend([
288+
MaybeRelocatable::from(calldata_start).into(),
289+
MaybeRelocatable::from(calldata_end).into(),
290+
]);
291+
let entrypoint_args: Vec<&CairoArg> = entrypoint_args.iter().collect();
292+
293+
// Run contract entrypoint
294+
295+
runner.run_from_entrypoint(
296+
entrypoint_offset,
297+
&entrypoint_args,
298+
run_resources,
299+
true,
300+
Some(runner.program.shared_program_data.data.len() + program_extra_data.len()),
301+
&mut vm,
302+
&mut hint_processor,
303+
)?;
304+
305+
// Check return values
306+
let return_values = vm.get_return_values(5).unwrap();
307+
let retdata_start = return_values[3].get_relocatable().unwrap();
308+
let retdata_end = return_values[4].get_relocatable().unwrap();
309+
let retdata: Vec<Felt252> = vm
310+
.get_integer_range(retdata_start, (retdata_end - retdata_start).unwrap())
311+
.unwrap()
312+
.iter()
313+
.map(|c| c.clone().into_owned())
314+
.collect();
315+
Ok(retdata)
316+
}
317+
209318
#[cfg(feature = "cairo-1-hints")]
210319
fn get_casm_contract_builtins(
211320
contract_class: &CasmContractClass,

src/vm/errors/vm_errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ pub enum VirtualMachineError {
106106
EndOfProgram(usize),
107107
#[error("Could not reach the end of the program. Executed steps: {0}.")]
108108
StepsLimit(u64),
109+
#[error("Could not reach the end of the program. RunResources has no remaining steps.")]
110+
UnfinishedExecution,
109111
#[error("Current run is not finished")]
110112
RunNotFinished,
111113
#[error("Invalid argument count, expected {} but got {}", (*.0).0, (*.0).1)]

src/vm/errors/vm_exception.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ mod test {
643643

644644
let end = cairo_runner.initialize(&mut vm).unwrap();
645645
assert!(cairo_runner
646-
.run_until_pc(end, &mut vm, &mut hint_processor)
646+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
647647
.is_err());
648648

649649
#[cfg(all(feature = "std"))]
@@ -657,7 +657,7 @@ mod test {
657657

658658
let end = cairo_runner.initialize(&mut vm).unwrap();
659659
assert!(cairo_runner
660-
.run_until_pc(end, &mut vm, &mut hint_processor)
660+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
661661
.is_err());
662662
assert_eq!(get_traceback(&vm, &cairo_runner), Some(expected_traceback));
663663
}
@@ -695,7 +695,7 @@ cairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60)
695695

696696
let end = cairo_runner.initialize(&mut vm).unwrap();
697697
assert!(cairo_runner
698-
.run_until_pc(end, &mut vm, &mut hint_processor)
698+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
699699
.is_err());
700700
assert_eq!(
701701
get_traceback(&vm, &cairo_runner),
@@ -854,7 +854,7 @@ cairo_programs/bad_programs/bad_range_check.cairo:11:5: (pc=0:6)
854854

855855
let end = cairo_runner.initialize(&mut vm).unwrap();
856856
let error = cairo_runner
857-
.run_until_pc(end, &mut vm, &mut hint_processor)
857+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
858858
.unwrap_err();
859859
let vm_excepction = VmException::from_vm_error(&cairo_runner, &vm, error);
860860
assert_eq!(vm_excepction.to_string(), expected_error_string);
@@ -899,7 +899,7 @@ cairo_programs/bad_programs/bad_usort.cairo:64:5: (pc=0:60)
899899

900900
let end = cairo_runner.initialize(&mut vm).unwrap();
901901
let error = cairo_runner
902-
.run_until_pc(end, &mut vm, &mut hint_processor)
902+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
903903
.unwrap_err();
904904
let vm_excepction = VmException::from_vm_error(&cairo_runner, &vm, error);
905905
assert_eq!(vm_excepction.to_string(), expected_error_string);

src/vm/hooks.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ mod tests {
146146

147147
let end = cairo_runner.initialize(&mut vm).unwrap();
148148
assert!(cairo_runner
149-
.run_until_pc(end, &mut vm, &mut hint_processor)
149+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
150150
.is_ok());
151151
}
152152

@@ -194,7 +194,7 @@ mod tests {
194194

195195
let end = cairo_runner.initialize(&mut vm).unwrap();
196196
assert!(cairo_runner
197-
.run_until_pc(end, &mut vm, &mut hint_processor)
197+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
198198
.is_err());
199199

200200
// Pre step fail
@@ -205,7 +205,7 @@ mod tests {
205205

206206
let end = cairo_runner.initialize(&mut vm).unwrap();
207207
assert!(cairo_runner
208-
.run_until_pc(end, &mut vm, &mut hint_processor)
208+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
209209
.is_err());
210210

211211
// Post step fail
@@ -216,7 +216,7 @@ mod tests {
216216

217217
let end = cairo_runner.initialize(&mut vm).unwrap();
218218
assert!(cairo_runner
219-
.run_until_pc(end, &mut vm, &mut hint_processor)
219+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
220220
.is_err());
221221
}
222222

@@ -267,7 +267,7 @@ mod tests {
267267

268268
let end = cairo_runner.initialize(&mut vm).unwrap();
269269
assert!(cairo_runner
270-
.run_until_pc(end, &mut vm, &mut hint_processor)
270+
.run_until_pc(end, &mut None, &mut vm, &mut hint_processor)
271271
.is_ok());
272272
}
273273
}

src/vm/runners/builtin_runner/bitwise.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ mod tests {
359359
let address = cairo_runner.initialize(&mut vm).unwrap();
360360

361361
cairo_runner
362-
.run_until_pc(address, &mut vm, &mut hint_processor)
362+
.run_until_pc(address, &mut None, &mut vm, &mut hint_processor)
363363
.unwrap();
364364

365365
assert_eq!(builtin.get_used_cells_and_allocated_size(&vm), Ok((0, 5)));
@@ -404,7 +404,7 @@ mod tests {
404404
let address = cairo_runner.initialize(&mut vm).unwrap();
405405

406406
cairo_runner
407-
.run_until_pc(address, &mut vm, &mut hint_processor)
407+
.run_until_pc(address, &mut None, &mut vm, &mut hint_processor)
408408
.unwrap();
409409

410410
assert_eq!(builtin.get_allocated_memory_units(&vm), Ok(5));

src/vm/runners/builtin_runner/ec_op.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ mod tests {
445445
let address = cairo_runner.initialize(&mut vm).unwrap();
446446

447447
cairo_runner
448-
.run_until_pc(address, &mut vm, &mut hint_processor)
448+
.run_until_pc(address, &mut None, &mut vm, &mut hint_processor)
449449
.unwrap();
450450

451451
assert_eq!(builtin.get_used_cells_and_allocated_size(&vm), Ok((0, 7)));
@@ -490,7 +490,7 @@ mod tests {
490490
let address = cairo_runner.initialize(&mut vm).unwrap();
491491

492492
cairo_runner
493-
.run_until_pc(address, &mut vm, &mut hint_processor)
493+
.run_until_pc(address, &mut None, &mut vm, &mut hint_processor)
494494
.unwrap();
495495

496496
assert_eq!(builtin.get_allocated_memory_units(&vm), Ok(7));

0 commit comments

Comments
 (0)