diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e0afbb34a..80505f88ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Upcoming Changes +* feat: add ExecutionState structure and get_execution_state method [#2043](https://github.com/lambdaclass/cairo-vm/pull/2043) + * feat: add get_current_step getter [#2034](https://github.com/lambdaclass/cairo-vm/pull/2034) * feat: implement VirtualMachine::is_accessed [#2033](https://github.com/lambdaclass/cairo-vm/pull/2033) diff --git a/vm/src/tests/mod.rs b/vm/src/tests/mod.rs index ecf44b2c71..ca8321ec9b 100644 --- a/vm/src/tests/mod.rs +++ b/vm/src/tests/mod.rs @@ -327,3 +327,30 @@ fn get_casm_contract_builtins( .map(|s| BuiltinName::from_str(s).expect("Invalid builtin name")) .collect() } + +#[cfg(test)] +mod execution_state_tests { + use crate::vm::vm_core::VirtualMachine; + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn test_get_execution_state_integration() { + // Create a virtual machine directly for testing + let mut vm = VirtualMachine::new(true, false); + + // Set some values for testing + vm.run_context.ap = 123; + vm.run_context.fp = 456; + vm.current_step = 10; + + // Get the execution state + let execution_state = vm.get_execution_state(); + + // Check the main state attributes + assert_eq!(execution_state.ap, 123); + assert_eq!(execution_state.fp, 456); + assert_eq!(execution_state.current_step, 10); + assert_eq!(execution_state.run_finished, false); // Expect false as we didn't set it + assert!(execution_state.memory_segments_count > 0); + } +} diff --git a/vm/src/vm/vm_core.rs b/vm/src/vm/vm_core.rs index be89d2821d..11d8289ec4 100644 --- a/vm/src/vm/vm_core.rs +++ b/vm/src/vm/vm_core.rs @@ -103,6 +103,25 @@ pub struct VirtualMachine { pub(crate) relocation_table: Option>, } +/// Structure for storing the execution state of a virtual machine +#[derive(Debug, Clone, PartialEq)] +pub struct ExecutionState { + /// Current program counter (Program Counter) + pub pc: Relocatable, + /// Current allocation pointer (Allocation Pointer) + pub ap: usize, + /// Current frame pointer (Frame Pointer) + pub fp: usize, + /// Current execution step + pub current_step: usize, + /// Whether execution is finished + pub run_finished: bool, + /// Number of memory segments + pub memory_segments_count: usize, + /// Information about active built-ins + pub active_builtins: Vec, +} + impl VirtualMachine { pub fn new(trace_enabled: bool, disable_trace_padding: bool) -> VirtualMachine { let run_context = RunContext { @@ -1249,6 +1268,30 @@ impl VirtualMachine { .finalize(Some(info.size), info.index as usize, None) } } + + /// Returns the current execution state of the virtual machine + /// + /// This function gathers all important components of the VM state, including + /// the current registers (pc, ap, fp), execution step information, and + /// active built-in functions. + /// + /// # Return value + /// + /// `ExecutionState` structure containing the current VM state + pub fn get_execution_state(&self) -> ExecutionState { + ExecutionState { + pc: self.run_context.pc, + ap: self.run_context.ap, + fp: self.run_context.fp, + current_step: self.current_step, + run_finished: self.run_finished, + memory_segments_count: self.segments.num_segments(), + active_builtins: self.builtin_runners + .iter() + .map(|runner| runner.name().to_string()) + .collect(), + } + } } pub struct VirtualMachineBuilder { @@ -5390,4 +5433,29 @@ mod tests { Some(6) ); } + + #[test] + #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)] + fn get_execution_state_test() { + let mut vm = vm!(); + vm.run_context.ap = 1; + vm.run_context.fp = 2; + vm.run_context.pc = Relocatable::from((3, 4)); + vm.current_step = 5; + vm.run_finished = true; + vm.builtin_runners.push(BuiltinRunner::from(HashBuiltinRunner::new( + Some(12), + true, + ))); + vm.segments.segment_used_sizes = Some(vec![1]); + + let execution_state = vm.get_execution_state(); + assert_eq!(execution_state.pc, Relocatable::from((3, 4))); + assert_eq!(execution_state.ap, 1); + assert_eq!(execution_state.fp, 2); + assert_eq!(execution_state.current_step, 5); + assert_eq!(execution_state.run_finished, true); + assert_eq!(execution_state.memory_segments_count, 1); + assert_eq!(execution_state.active_builtins, vec!["pedersen".to_string()]); + } }