Skip to content

Conversation

@eytan-starkware
Copy link
Contributor

@eytan-starkware eytan-starkware commented Jan 15, 2026

Summary

Added support for capturing and returning VM execution traces in the Cairo runner. This enables checking real run output, debugging and analysis of Cairo program execution by providing access to the program counter, allocation pointer, and frame pointer at each step, as well as the final memory state.


Type of change

Please check one:

  • Bug fix (fixes incorrect behavior)
  • New feature
  • Performance improvement
  • Documentation change with concrete technical impact
  • Style, wording, formatting, or typo-only change

⚠️ Note:
To keep maintainer workload sustainable, we generally do not accept PRs that
are only minor wording, grammar, formatting, or style changes.
Such PRs may be closed without detailed review.


Why is this change needed?

This PR adds the ability to capture and return VM execution traces, which is essential for debugging and analyzing Cairo program execution. The trace provides visibility into the program counter, allocation pointer, and frame pointer at each execution step, along with the final memory state. This is particularly useful for developers who need to understand the low-level execution details of their Cairo programs.


What was the behavior or documentation before?

Previously, the runner would execute Cairo programs but did not provide a way to access the execution trace or memory state after execution. This made debugging complex programs difficult as developers couldn't inspect the execution flow.


What is the behavior or documentation after?

The runner now has the ability to optionally capture and return the execution trace and memory state. This is implemented through:

  1. Added trace field to RunResult and RunResultStarknet structs
  2. Added run_function_with_starknet_context_with_trace method with a return_trace parameter
  3. Updated existing methods to support trace capture
  4. Added test infrastructure to demonstrate and validate trace capture functionality

The e2e test runner now supports a trace: true option and can display the execution trace in a readable table format.


Additional context

The implementation includes comprehensive test cases that demonstrate the trace functionality with different Cairo programs, from simple arithmetic to more complex control flow and loops. This provides examples for users on how to use and interpret the trace data.

@reviewable-StarkWare
Copy link

This change is Reviewable

Copy link
Contributor Author

eytan-starkware commented Jan 15, 2026

@eytan-starkware eytan-starkware force-pushed the eytan_graphite/_test_adding_casm_trace_to_boxed_enum_e2e_tests branch from 9feac89 to 0cd7778 Compare January 15, 2026 12:22
@eytan-starkware eytan-starkware changed the title Changed felt252 deseralization to be based on an iterator. (#9470) (test): Adding casm run and trace to e2e tests Jan 15, 2026
@eytan-starkware eytan-starkware marked this pull request as ready for review January 15, 2026 12:23
Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi reviewed 1 file and all commit messages, and made 1 comment.
Reviewable status: 1 of 6 files reviewed, 1 unresolved discussion (waiting on @eytan-starkware and @TomerStarkware).


tests/e2e_test.rs line 521 at r1 (raw file):

                .join("\n");
            res.insert("memory".into(), memory_str);
        }

remove everything this requires as well.

printing the trace is good for debug - but for now rather not have the extra "baggage" of getting the trace as part of the function runner flow.

Code quote:

        if params.include_trace {
            // Format trace as a table with headers.
            let trace = match result.trace {
                Some(trace) => trace,
                None => {
                    return TestRunnerResult {
                        outputs: res,
                        error: Some(
                            "trace: true was specified but no trace was returned. Ensure the \
                             function was executed correctly."
                                .to_string(),
                        ),
                    };
                }
            };
            let mut trace_lines = vec!["| PC | AP | FP |".to_string()];
            for entry in &trace {
                trace_lines.push(format!("| {} | {} | {} |", entry.pc, entry.ap, entry.fp));
            }
            res.insert("casm_trace".into(), trace_lines.join("\n"));

            // Include memory state.
            let memory_str = result
                .memory
                .iter()
                .enumerate()
                .filter_map(|(addr, value)| value.as_ref().map(|v| format!("[{}] = {}", addr, v)))
                .join("\n");
            res.insert("memory".into(), memory_str);
        }

Copy link
Contributor Author

@eytan-starkware eytan-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eytan-starkware made 1 comment.
Reviewable status: 1 of 6 files reviewed, 1 unresolved discussion (waiting on @orizi and @TomerStarkware).


tests/e2e_test.rs line 521 at r1 (raw file):

Previously, orizi wrote…

remove everything this requires as well.

printing the trace is good for debug - but for now rather not have the extra "baggage" of getting the trace as part of the function runner flow.

Done.

Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi reviewed 3 files and all commit messages, made 2 comments, and resolved 1 discussion.
Reviewable status: 4 of 6 files reviewed, 2 unresolved discussions (waiting on @eytan-starkware and @TomerStarkware).


tests/e2e_test_data/libfuncs/casm_run_sanity line 35 at r2 (raw file):


//! > casm_trace
| PC | AP | FP |

remove unproduced.


tests/e2e_test.rs line 250 at r2 (raw file):

    /// Parses test_data format: "function_name(input)=output"
    /// Allows whitespace around all components.
    fn parse(s: &str) -> Result<Self, String> {

f2f

@eytan-starkware eytan-starkware force-pushed the eytan_graphite/_test_adding_casm_trace_to_boxed_enum_e2e_tests branch 2 times, most recently from bf6b4e1 to 44b56da Compare January 18, 2026 14:03
Copy link
Contributor Author

@eytan-starkware eytan-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eytan-starkware made 2 comments.
Reviewable status: 2 of 6 files reviewed, 2 unresolved discussions (waiting on @orizi and @TomerStarkware).


tests/e2e_test.rs line 250 at r2 (raw file):

Previously, orizi wrote…

f2f

Done.


tests/e2e_test_data/libfuncs/casm_run_sanity line 35 at r2 (raw file):

Previously, orizi wrote…

remove unproduced.

Done.

Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi reviewed all commit messages and made 2 comments.
Reviewable status: 2 of 6 files reviewed, 4 unresolved discussions (waiting on @eytan-starkware and @TomerStarkware).


tests/e2e_test_data/libfuncs/casm_run_sanity line 11 at r3 (raw file):

}

//! > casm

Suggestion:

//! > Output
8

//! > casm

tests/e2e_test.rs line 239 at r3 (raw file):

    function_name: String,
    input: Felt252,
    expected_output: Felt252,

Suggestion:

    function_name: String,
    input: Vec<Felt252>,
    expected_output: Vec<Felt252>,

Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi resolved 2 discussions.
Reviewable status: 2 of 6 files reviewed, 2 unresolved discussions (waiting on @eytan-starkware and @TomerStarkware).

Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi resolved 1 discussion.
Reviewable status: 2 of 6 files reviewed, 1 unresolved discussion (waiting on @eytan-starkware and @TomerStarkware).

@eytan-starkware eytan-starkware force-pushed the eytan_graphite/_test_adding_casm_trace_to_boxed_enum_e2e_tests branch from 44b56da to 2f97046 Compare January 19, 2026 14:14
Copy link
Contributor Author

@eytan-starkware eytan-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eytan-starkware made 1 comment.
Reviewable status: 2 of 6 files reviewed, 1 unresolved discussion (waiting on @orizi and @TomerStarkware).


tests/e2e_test.rs line 239 at r3 (raw file):

    function_name: String,
    input: Felt252,
    expected_output: Felt252,

Done.

Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi reviewed 4 files and all commit messages, made 2 comments, and resolved 1 discussion.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @eytan-starkware and @TomerStarkware).


tests/e2e_test.rs line 421 at r4 (raw file):

            Default::default(),
        )
        .map_err(|e| format!("Failed running function '{}': {}", test_data.function_name, e))?;

Suggestion:

        .map_err(|e| format!("Failed running function '{}': {e}", test_data.function_name))?;

tests/e2e_test.rs line 438 at r4 (raw file):

            "Function '{}' panicked with data: {:?}",
            test_data.function_name, panic_data
        )),

Suggestion:

        RunResultValue::Panic(panic_data) => Err(format!(
            "Function '{}' panicked with data: {panic_data:?}",
            test_data.function_name
        )),

@eytan-starkware eytan-starkware force-pushed the eytan_graphite/_test_adding_casm_trace_to_boxed_enum_e2e_tests branch from 2f97046 to f07d02a Compare January 20, 2026 10:46
Copy link
Contributor Author

@eytan-starkware eytan-starkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eytan-starkware made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @orizi and @TomerStarkware).


tests/e2e_test.rs line 438 at r4 (raw file):

            "Function '{}' panicked with data: {:?}",
            test_data.function_name, panic_data
        )),

Done.

Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@orizi reviewed 1 file and all commit messages, made 1 comment, and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @TomerStarkware).

@eytan-starkware eytan-starkware force-pushed the eytan_graphite/_test_adding_casm_trace_to_boxed_enum_e2e_tests branch from f07d02a to 9825250 Compare January 20, 2026 12:08
Copy link
Collaborator

@orizi orizi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@orizi reviewed 1 file and all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @TomerStarkware).

@eytan-starkware eytan-starkware added this pull request to the merge queue Jan 20, 2026
Merged via the queue into main with commit 38e928d Jan 20, 2026
55 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants