From 528d55460b20955337fa8ce453e2c06a7d354022 Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Tue, 2 Apr 2024 20:13:08 +0200 Subject: [PATCH 01/12] add phantom nodes on deploy with no constructor --- .../execution/entry_point.rs | 1 + .../rpc.rs | 6 +++ .../forge_runtime_extension/mod.rs | 4 ++ crates/cheatnet/src/state.rs | 43 +++++++++++++------ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs index e48fb39a77..106d381efe 100644 --- a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs +++ b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs @@ -220,6 +220,7 @@ pub fn execute_constructor_entry_point( let contract_class = state.get_compiled_contract_class(ctor_context.class_hash)?; let Some(constructor_selector) = contract_class.constructor_selector() else { // Contract has no constructor. + runtime_state.cheatnet_state.trace_data.add_phantom_call(); return handle_empty_constructor(ctor_context, calldata, remaining_gas); }; diff --git a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs index c553c4a6b8..d7f62923ca 100644 --- a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs +++ b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs @@ -39,6 +39,12 @@ pub enum CallResult { Failure(CallFailure), } +impl Default for CallResult { + fn default() -> Self { + Self::Success { ret_data: vec![] } + } +} + /// Enum representing possible call failure and its' type. /// `Panic` - Recoverable, meant to be caught by the user. /// `Error` - Unrecoverable, equivalent of panic! in rust. diff --git a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs index ee2a3a32a1..e28f284f8a 100644 --- a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs +++ b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs @@ -684,6 +684,10 @@ fn handle_deploy_result( // append all to one output Vec instead of allocating new one for each nested call fn serialize_call_trace(call_trace: &CallTrace, output: &mut Vec) { + if !call_trace.node_type.is_visible_to_user() { + return; + } + serialize_call_entry_point(&call_trace.entry_point, output); output.push(Felt252::from(call_trace.nested_calls.len())); diff --git a/crates/cheatnet/src/state.rs b/crates/cheatnet/src/state.rs index 15f4b11f40..44ccba9e12 100644 --- a/crates/cheatnet/src/state.rs +++ b/crates/cheatnet/src/state.rs @@ -149,6 +149,7 @@ impl CheatStatus { } /// Tree structure representing trace of a call. +#[derive(Default)] pub struct CallTrace { pub entry_point: CallEntryPoint, // These also include resources used by internal calls @@ -158,6 +159,24 @@ pub struct CallTrace { pub nested_calls: Vec>>, pub result: CallResult, pub vm_trace: Option>, + pub node_type: NodeType, +} + +#[derive(Default)] +pub enum NodeType { + #[default] + Regular, + Phantom, +} + +impl NodeType { + #[must_use] + pub fn is_visible_to_user(&self) -> bool { + match *self { + NodeType::Regular => true, + NodeType::Phantom => false, + } + } } #[derive(Clone)] @@ -259,12 +278,7 @@ impl Default for CheatnetState { test_code_entry_point.class_hash = Some(class_hash!(TEST_CONTRACT_CLASS_HASH)); let test_call = Rc::new(RefCell::new(CallTrace { entry_point: test_code_entry_point, - used_execution_resources: Default::default(), - used_l1_resources: Default::default(), - used_syscalls: Default::default(), - nested_calls: vec![], - result: CallResult::Success { ret_data: vec![] }, - vm_trace: None, + ..Default::default() })); Self { rolled_contracts: Default::default(), @@ -396,12 +410,7 @@ impl TraceData { ) { let new_call = Rc::new(RefCell::new(CallTrace { entry_point, - used_execution_resources: Default::default(), - used_l1_resources: Default::default(), - used_syscalls: Default::default(), - nested_calls: vec![], - result: CallResult::Success { ret_data: vec![] }, - vm_trace: None, + ..Default::default() })); let current_call = self.current_call_stack.top(); @@ -446,6 +455,16 @@ impl TraceData { last_call.result = result; last_call.vm_trace = vm_trace; } + + pub fn add_phantom_call(&mut self) { + let new_call = Rc::new(RefCell::new(CallTrace { + node_type: NodeType::Phantom, + ..Default::default() + })); + let current_call = self.current_call_stack.top(); + + current_call.borrow_mut().nested_calls.push(new_call); + } } fn get_cheat_for_contract( From c2c9ee7c2a5cf4cd8248b666e042fd58586f3a1e Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Wed, 3 Apr 2024 14:37:49 +0200 Subject: [PATCH 02/12] add test --- Cargo.lock | 2 +- Cargo.toml | 2 +- .../forge_runtime_extension/mod.rs | 8 ++++- crates/cheatnet/src/state.rs | 2 +- crates/forge-runner/src/build_trace_data.rs | 12 +++++-- .../tests/data/trace/tests/test_trace.cairo | 2 +- crates/forge/tests/e2e/build_trace_data.rs | 32 +++++++++++++++++-- 7 files changed, 50 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4bdd3dc5fa..7cf9a89420 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5263,7 +5263,7 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "trace-data" version = "0.2.0" -source = "git+https://github.com/software-mansion/cairo-profiler/?rev=3af0782#3af07829cca6ad36f753418b368693f5698264d6" +source = "git+https://github.com/software-mansion/cairo-profiler/?rev=185216e#185216eb438771be482d5a01fb5b963d4cabd627" dependencies = [ "serde", ] diff --git a/Cargo.toml b/Cargo.toml index 5a96e6752c..e0fa5937ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ regex = "1.10.4" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" starknet = { git = "https://github.com/xJonathanLEI/starknet-rs", rev = "d980869" } -trace-data = { git = "https://github.com/software-mansion/cairo-profiler/", rev = "3af0782" } +trace-data = { git = "https://github.com/software-mansion/cairo-profiler/", rev = "185216e" } tempfile = "3.10.1" thiserror = "1.0.58" ctor = "0.2.7" diff --git a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs index e28f284f8a..a77dbfe2bd 100644 --- a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs +++ b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs @@ -1,4 +1,5 @@ use self::contracts_data::ContractsData; +use crate::state::NodeType; use crate::{ runtime_extensions::{ call_to_blockifier_runtime_extension::{ @@ -690,7 +691,12 @@ fn serialize_call_trace(call_trace: &CallTrace, output: &mut Vec) { serialize_call_entry_point(&call_trace.entry_point, output); - output.push(Felt252::from(call_trace.nested_calls.len())); + let visible_calls_count = call_trace + .nested_calls + .iter() + .filter(|call| call.borrow().node_type == NodeType::Regular) + .count(); + output.push(Felt252::from(visible_calls_count)); for call_trace in &call_trace.nested_calls { serialize_call_trace(&call_trace.borrow(), output); diff --git a/crates/cheatnet/src/state.rs b/crates/cheatnet/src/state.rs index 44ccba9e12..33b2a4cac1 100644 --- a/crates/cheatnet/src/state.rs +++ b/crates/cheatnet/src/state.rs @@ -162,7 +162,7 @@ pub struct CallTrace { pub node_type: NodeType, } -#[derive(Default)] +#[derive(Default, Copy, Clone, PartialEq)] pub enum NodeType { #[default] Regular, diff --git a/crates/forge-runner/src/build_trace_data.rs b/crates/forge-runner/src/build_trace_data.rs index 609369656f..671e7c532f 100644 --- a/crates/forge-runner/src/build_trace_data.rs +++ b/crates/forge-runner/src/build_trace_data.rs @@ -12,7 +12,7 @@ use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use cairo_vm::vm::trace::trace_entry::TraceEntry; use cheatnet::constants::{TEST_CONTRACT_CLASS_HASH, TEST_ENTRY_POINT_SELECTOR}; use cheatnet::runtime_extensions::forge_runtime_extension::contracts_data::ContractsData; -use cheatnet::state::CallTrace; +use cheatnet::state::{CallTrace, NodeType}; use conversions::IntoConv; use itertools::Itertools; use starknet::core::utils::get_selector_from_name; @@ -25,7 +25,7 @@ use trace_data::{ CallType as ProfilerCallType, ContractAddress, DeprecatedSyscallSelector as ProfilerDeprecatedSyscallSelector, EntryPointSelector, EntryPointType as ProfilerEntryPointType, ExecutionResources as ProfilerExecutionResources, - TraceEntry as ProfilerTraceEntry, VmExecutionResources, + NodeType as ProfilerNodeType, TraceEntry as ProfilerTraceEntry, VmExecutionResources, }; pub const TRACE_DIR: &str = ".snfoundry_trace"; @@ -58,6 +58,7 @@ pub fn build_profiler_call_trace( .map(|c| build_profiler_call_trace(c, contracts_data)) .collect(), vm_trace, + node_type: build_profiler_node_type(value.node_type), } } @@ -211,6 +212,13 @@ fn build_profiler_trace_entry(value: &TraceEntry) -> ProfilerTraceEntry { } } +fn build_profiler_node_type(value: NodeType) -> ProfilerNodeType { + match value { + NodeType::Regular => ProfilerNodeType::Regular, + NodeType::Phantom => ProfilerNodeType::Phantom, + } +} + pub fn save_trace_data(test_name: &String, trace_data: &ProfilerCallTrace) -> Result { let serialized_trace = serde_json::to_string(trace_data).expect("Failed to serialize call trace"); diff --git a/crates/forge/tests/data/trace/tests/test_trace.cairo b/crates/forge/tests/data/trace/tests/test_trace.cairo index 0ce23922e8..78831eeeec 100644 --- a/crates/forge/tests/data/trace/tests/test_trace.cairo +++ b/crates/forge/tests/data/trace/tests/test_trace.cairo @@ -8,7 +8,7 @@ use trace_info::{ #[test] #[feature("safe_dispatcher")] -fn test_trace_print() { +fn test_trace() { let sc = declare("SimpleContract").unwrap(); let (contract_address_A, _) = sc.deploy(@array![]).unwrap(); diff --git a/crates/forge/tests/e2e/build_trace_data.rs b/crates/forge/tests/e2e/build_trace_data.rs index a6c3039e19..ed37e65f72 100644 --- a/crates/forge/tests/e2e/build_trace_data.rs +++ b/crates/forge/tests/e2e/build_trace_data.rs @@ -1,7 +1,7 @@ use super::common::runner::{setup_package, test_runner}; use forge_runner::build_trace_data::{TEST_CODE_CONTRACT_NAME, TEST_CODE_FUNCTION_NAME, TRACE_DIR}; use std::fs; -use trace_data::CallTrace as ProfilerCallTrace; +use trace_data::{CallTrace as ProfilerCallTrace, NodeType}; #[test] fn simple_package_save_trace() { @@ -50,7 +50,7 @@ fn trace_has_contract_and_function_names() { let trace_data = fs::read_to_string( temp.join(TRACE_DIR) - .join("tests::test_trace::test_trace_print.json"), + .join("tests::test_trace::test_trace.json"), ) .unwrap(); @@ -97,7 +97,7 @@ fn trace_has_vm_trace() { let trace_data = fs::read_to_string( temp.join(TRACE_DIR) - .join("tests::test_trace::test_trace_print.json"), + .join("tests::test_trace::test_trace.json"), ) .unwrap(); @@ -116,3 +116,29 @@ fn assert_vm_trace_exists(trace: &ProfilerCallTrace) { assert_vm_trace_exists(sub_trace); } } + +#[test] +fn trace_has_deploy_with_no_constructor_phantom_nodes() { + let temp = setup_package("trace"); + let snapbox = test_runner(&temp); + + snapbox + .arg("--save-trace-data") + .current_dir(&temp) + .assert() + .success(); + + let trace_data = fs::read_to_string( + temp.join(TRACE_DIR) + .join("tests::test_trace::test_trace.json"), + ) + .unwrap(); + + let call_trace: ProfilerCallTrace = + serde_json::from_str(&trace_data).expect("Failed to parse call_trace"); + + // 3 first calls are deploys with empty constructors + matches!(call_trace.nested_calls[0].node_type, NodeType::Phantom); + matches!(call_trace.nested_calls[1].node_type, NodeType::Phantom); + matches!(call_trace.nested_calls[2].node_type, NodeType::Phantom); +} From 40f86e37a7d729a0b4f9dcd8e1a32e5944cefcd0 Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Wed, 3 Apr 2024 15:33:50 +0200 Subject: [PATCH 03/12] fix --- crates/forge/tests/e2e/trace_print.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/forge/tests/e2e/trace_print.rs b/crates/forge/tests/e2e/trace_print.rs index d82c18c757..ca880163d7 100644 --- a/crates/forge/tests/e2e/trace_print.rs +++ b/crates/forge/tests/e2e/trace_print.rs @@ -89,7 +89,7 @@ fn trace_info_print() { ] Call Result: Success: [] - [PASS] tests::test_trace::test_trace_print (gas: [..] + [PASS] tests::test_trace::test_trace (gas: [..] Tests: 1 passed, 0 failed, 0 skipped, 0 ignored, 0 filtered out "}, ); From 4e86f31f23a097e6df0fd0396db8b6d69aaa7574 Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Wed, 3 Apr 2024 15:48:17 +0200 Subject: [PATCH 04/12] fix testsg --- crates/forge/tests/e2e/build_trace_data.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/forge/tests/e2e/build_trace_data.rs b/crates/forge/tests/e2e/build_trace_data.rs index ed37e65f72..2fa8b44a18 100644 --- a/crates/forge/tests/e2e/build_trace_data.rs +++ b/crates/forge/tests/e2e/build_trace_data.rs @@ -80,7 +80,9 @@ fn assert_contract_and_function_names(trace: &ProfilerCallTrace) { ); for sub_trace in &trace.nested_calls { - assert_contract_and_function_names(sub_trace); + if matches!(trace.node_type, NodeType::Regular) { + assert_contract_and_function_names(sub_trace); + } } } From b435abf67d6bbaebfb7c237ac39af26b19cc9541 Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Thu, 4 Apr 2024 10:08:39 +0200 Subject: [PATCH 05/12] fix tests --- .../forge_runtime_extension/mod.rs | 2 +- crates/cheatnet/src/state.rs | 2 +- crates/forge/tests/e2e/build_trace_data.rs | 10 ++-- crates/forge/tests/e2e/trace_resources.rs | 46 ++++++++++--------- 4 files changed, 32 insertions(+), 28 deletions(-) diff --git a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs index a77dbfe2bd..6d37a86025 100644 --- a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs +++ b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs @@ -694,7 +694,7 @@ fn serialize_call_trace(call_trace: &CallTrace, output: &mut Vec) { let visible_calls_count = call_trace .nested_calls .iter() - .filter(|call| call.borrow().node_type == NodeType::Regular) + .filter(|call| matches!(call.borrow().node_type, NodeType::Regular)) .count(); output.push(Felt252::from(visible_calls_count)); diff --git a/crates/cheatnet/src/state.rs b/crates/cheatnet/src/state.rs index 33b2a4cac1..d67e35983c 100644 --- a/crates/cheatnet/src/state.rs +++ b/crates/cheatnet/src/state.rs @@ -162,7 +162,7 @@ pub struct CallTrace { pub node_type: NodeType, } -#[derive(Default, Copy, Clone, PartialEq)] +#[derive(Default, Copy, Clone)] pub enum NodeType { #[default] Regular, diff --git a/crates/forge/tests/e2e/build_trace_data.rs b/crates/forge/tests/e2e/build_trace_data.rs index 2fa8b44a18..b7d37b8b09 100644 --- a/crates/forge/tests/e2e/build_trace_data.rs +++ b/crates/forge/tests/e2e/build_trace_data.rs @@ -65,7 +65,7 @@ fn trace_has_contract_and_function_names() { call_trace.entry_point.function_name, Some(String::from(TEST_CODE_FUNCTION_NAME)) ); - assert_contract_and_function_names(&call_trace.nested_calls[0]); + assert_contract_and_function_names(&call_trace.nested_calls[3]); } fn assert_contract_and_function_names(trace: &ProfilerCallTrace) { @@ -80,9 +80,7 @@ fn assert_contract_and_function_names(trace: &ProfilerCallTrace) { ); for sub_trace in &trace.nested_calls { - if matches!(trace.node_type, NodeType::Regular) { - assert_contract_and_function_names(sub_trace); - } + assert_contract_and_function_names(sub_trace); } } @@ -111,7 +109,9 @@ fn trace_has_vm_trace() { fn assert_vm_trace_exists(trace: &ProfilerCallTrace) { assert!( - trace.vm_trace.is_some() || trace.entry_point.function_name == Some(String::from("fail")) + trace.vm_trace.is_some() + || trace.entry_point.function_name == Some(String::from("fail")) + || matches!(trace.node_type, NodeType::Phantom) ); for sub_trace in &trace.nested_calls { diff --git a/crates/forge/tests/e2e/trace_resources.rs b/crates/forge/tests/e2e/trace_resources.rs index 5e256c7c3e..5e0ea38ecc 100644 --- a/crates/forge/tests/e2e/trace_resources.rs +++ b/crates/forge/tests/e2e/trace_resources.rs @@ -76,7 +76,9 @@ fn check_vm_resources_and_easily_unifiable_syscalls( ) -> &ProfilerExecutionResources { let mut child_resources = vec![]; for call in &call_trace.nested_calls { - child_resources.push(check_vm_resources_and_easily_unifiable_syscalls(call)); + if matches!(call.node_type, trace_data::NodeType::Regular) { + child_resources.push(check_vm_resources_and_easily_unifiable_syscalls(call)); + } } let mut sum_child_resources = ProfilerExecutionResources::default(); @@ -146,34 +148,34 @@ fn assert_l2_l1_messages(call_trace: &ProfilerCallTrace) { ); } -// When sth fails in the functions below and you didn't change anything in the cairo code it is a BUG. +// When sth fails in the functions below, and you didn't change anything in the cairo code it is a BUG. // If you changed the corresponding cairo code count the expected occurrences of syscalls manually first, then assert them. // TL;DR: DON't mindlessly change numbers to fix the tests if they ever fail. fn check_call(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 14, 8, 1); - let regular_call = &test_call_trace.nested_calls[1]; + let regular_call = &test_call_trace.nested_calls[4]; assert_not_easily_unifiable_syscalls(regular_call, 2, 1, 0); - let from_proxy = ®ular_call.nested_calls[0]; + let from_proxy = ®ular_call.nested_calls[1]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let with_libcall = &test_call_trace.nested_calls[2]; + let with_libcall = &test_call_trace.nested_calls[5]; assert_not_easily_unifiable_syscalls(with_libcall, 2, 0, 1); - let from_proxy = &with_libcall.nested_calls[0]; + let from_proxy = &with_libcall.nested_calls[1]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let call_two = &test_call_trace.nested_calls[3]; + let call_two = &test_call_trace.nested_calls[6]; assert_not_easily_unifiable_syscalls(call_two, 3, 2, 0); let from_proxy = &call_two.nested_calls[0]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let from_proxy_dummy = &call_two.nested_calls[1]; + let from_proxy_dummy = &call_two.nested_calls[2]; assert_not_easily_unifiable_syscalls(from_proxy_dummy, 1, 0, 0); - let from_proxy = &test_call_trace.nested_calls[4]; + let from_proxy = &test_call_trace.nested_calls[7]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); } @@ -181,48 +183,50 @@ fn check_deploy(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 14, 4, 0); for deploy_proxy in &test_call_trace.nested_calls { - assert_not_easily_unifiable_syscalls(deploy_proxy, 2, 1, 0); + if matches!(deploy_proxy.node_type, trace_data::NodeType::Regular) { + assert_not_easily_unifiable_syscalls(deploy_proxy, 2, 1, 0); - let from_proxy = &deploy_proxy.nested_calls[0]; - assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); + let from_proxy = &deploy_proxy.nested_calls[1]; + assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); + } } } fn check_l1_handler(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 8, 3, 0); - let handle_l1 = &test_call_trace.nested_calls[1]; + let handle_l1 = &test_call_trace.nested_calls[3]; assert_not_easily_unifiable_syscalls(handle_l1, 3, 2, 0); - let regular_call = &handle_l1.nested_calls[0]; + let regular_call = &handle_l1.nested_calls[1]; assert_not_easily_unifiable_syscalls(regular_call, 2, 1, 0); - let from_proxy = ®ular_call.nested_calls[0]; + let from_proxy = ®ular_call.nested_calls[1]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); } fn check_libcall(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 11, 3, 5); - let regular_call = &test_call_trace.nested_calls[0]; + let regular_call = &test_call_trace.nested_calls[3]; assert_not_easily_unifiable_syscalls(regular_call, 2, 1, 0); - let from_proxy = ®ular_call.nested_calls[0]; + let from_proxy = ®ular_call.nested_calls[1]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let with_libcall = &test_call_trace.nested_calls[1]; + let with_libcall = &test_call_trace.nested_calls[4]; assert_not_easily_unifiable_syscalls(with_libcall, 2, 0, 1); - let call_two = &test_call_trace.nested_calls[2]; + let call_two = &test_call_trace.nested_calls[5]; assert_not_easily_unifiable_syscalls(call_two, 3, 2, 0); let from_proxy = &call_two.nested_calls[0]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let from_proxy_dummy = &call_two.nested_calls[1]; + let from_proxy_dummy = &call_two.nested_calls[2]; assert_not_easily_unifiable_syscalls(from_proxy_dummy, 1, 0, 0); - let from_proxy = &test_call_trace.nested_calls[3]; + let from_proxy = &test_call_trace.nested_calls[6]; assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); } From d249802e5420e5822528f42e6f5763b1be870ae1 Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Mon, 8 Apr 2024 15:45:38 +0200 Subject: [PATCH 06/12] fix stuff --- Cargo.lock | 2 +- Cargo.toml | 2 +- .../execution/entry_point.rs | 22 +++++--- .../forge_runtime_extension/mod.rs | 21 +++++--- crates/cheatnet/src/state.rs | 36 +++++-------- crates/forge-runner/src/build_trace_data.rs | 28 ++++++----- crates/forge/tests/e2e/build_trace_data.rs | 34 ++++++++----- crates/forge/tests/e2e/common/mod.rs | 10 ++++ crates/forge/tests/e2e/trace_resources.rs | 50 ++++++++++--------- 9 files changed, 115 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7cf9a89420..9157617e4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5263,7 +5263,7 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "trace-data" version = "0.2.0" -source = "git+https://github.com/software-mansion/cairo-profiler/?rev=185216e#185216eb438771be482d5a01fb5b963d4cabd627" +source = "git+https://github.com/software-mansion/cairo-profiler/?rev=8e3fa5b418b655acfa6c07c90cf5ccf7c297c381#8e3fa5b418b655acfa6c07c90cf5ccf7c297c381" dependencies = [ "serde", ] diff --git a/Cargo.toml b/Cargo.toml index e0fa5937ab..eca057ddb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ regex = "1.10.4" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" starknet = { git = "https://github.com/xJonathanLEI/starknet-rs", rev = "d980869" } -trace-data = { git = "https://github.com/software-mansion/cairo-profiler/", rev = "185216e" } +trace-data = { git = "https://github.com/software-mansion/cairo-profiler/", rev = "8e3fa5b418b655acfa6c07c90cf5ccf7c297c381" } tempfile = "3.10.1" thiserror = "1.0.58" ctor = "0.2.7" diff --git a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs index 106d381efe..ef02a93967 100644 --- a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs +++ b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/execution/entry_point.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use super::cairo1_execution::execute_entry_point_call_cairo1; use crate::runtime_extensions::call_to_blockifier_runtime_extension::execution::deprecated::cairo0_execution::execute_entry_point_call_cairo0; use crate::runtime_extensions::call_to_blockifier_runtime_extension::CheatnetState; -use crate::state::{CallTrace, CheatStatus}; +use crate::state::{CallTrace, CallTraceNode, CheatStatus}; use blockifier::execution::call_info::{CallExecution, Retdata}; use blockifier::{ execution::{ @@ -220,7 +220,9 @@ pub fn execute_constructor_entry_point( let contract_class = state.get_compiled_contract_class(ctor_context.class_hash)?; let Some(constructor_selector) = contract_class.constructor_selector() else { // Contract has no constructor. - runtime_state.cheatnet_state.trace_data.add_phantom_call(); + cheatnet_state + .trace_data + .add_deploy_without_constructor_node(); return handle_empty_constructor(ctor_context, calldata, remaining_gas); }; @@ -279,18 +281,22 @@ fn mocked_call_info(call: CallEntryPoint, ret_data: Vec) -> CallInfo fn aggregate_nested_syscall_counters(trace: &Rc>) -> SyscallCounter { let mut result = SyscallCounter::new(); - for nested_call in &trace.borrow().nested_calls { - let sub_trace_counter = aggregate_syscall_counters(nested_call); - result = sum_syscall_counters(result, &sub_trace_counter); + for nested_call_node in &trace.borrow().nested_calls { + if let CallTraceNode::EntryPointCall(nested_call) = nested_call_node { + let sub_trace_counter = aggregate_syscall_counters(nested_call); + result = sum_syscall_counters(result, &sub_trace_counter); + } } result } fn aggregate_syscall_counters(trace: &Rc>) -> SyscallCounter { let mut result = trace.borrow().used_syscalls.clone(); - for nested_call in &trace.borrow().nested_calls { - let sub_trace_counter = aggregate_nested_syscall_counters(nested_call); - result = sum_syscall_counters(result, &sub_trace_counter); + for nested_call_node in &trace.borrow().nested_calls { + if let CallTraceNode::EntryPointCall(nested_call) = nested_call_node { + let sub_trace_counter = aggregate_nested_syscall_counters(nested_call); + result = sum_syscall_counters(result, &sub_trace_counter); + } } result } diff --git a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs index 6d37a86025..d68559e48a 100644 --- a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs +++ b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs @@ -1,5 +1,5 @@ use self::contracts_data::ContractsData; -use crate::state::NodeType; +use crate::state::CallTraceNode; use crate::{ runtime_extensions::{ call_to_blockifier_runtime_extension::{ @@ -685,21 +685,19 @@ fn handle_deploy_result( // append all to one output Vec instead of allocating new one for each nested call fn serialize_call_trace(call_trace: &CallTrace, output: &mut Vec) { - if !call_trace.node_type.is_visible_to_user() { - return; - } - serialize_call_entry_point(&call_trace.entry_point, output); let visible_calls_count = call_trace .nested_calls .iter() - .filter(|call| matches!(call.borrow().node_type, NodeType::Regular)) + .filter(|call| matches!(call, CallTraceNode::EntryPointCall(_))) .count(); output.push(Felt252::from(visible_calls_count)); - for call_trace in &call_trace.nested_calls { - serialize_call_trace(&call_trace.borrow(), output); + for call_trace_node in &call_trace.nested_calls { + if let CallTraceNode::EntryPointCall(call_trace) = call_trace_node { + serialize_call_trace(&call_trace.borrow(), output); + } } serialize_call_result(&call_trace.result, output); @@ -830,6 +828,13 @@ pub fn update_top_call_execution_resources(runtime: &mut ForgeRuntime) { let nested_calls_syscalls = top_call .nested_calls .iter() + .filter_map(|trace_node| { + if let CallTraceNode::EntryPointCall(trace) = trace_node { + Some(trace) + } else { + None + } + }) .fold(SyscallCounter::new(), |syscalls, trace| { sum_syscall_counters(syscalls, &trace.borrow().used_syscalls) }); diff --git a/crates/cheatnet/src/state.rs b/crates/cheatnet/src/state.rs index d67e35983c..71521f6ea6 100644 --- a/crates/cheatnet/src/state.rs +++ b/crates/cheatnet/src/state.rs @@ -156,27 +156,16 @@ pub struct CallTrace { pub used_execution_resources: ExecutionResources, pub used_l1_resources: L1Resources, pub used_syscalls: SyscallCounter, - pub nested_calls: Vec>>, + pub nested_calls: Vec, pub result: CallResult, pub vm_trace: Option>, - pub node_type: NodeType, } -#[derive(Default, Copy, Clone)] -pub enum NodeType { - #[default] - Regular, - Phantom, -} - -impl NodeType { - #[must_use] - pub fn is_visible_to_user(&self) -> bool { - match *self { - NodeType::Regular => true, - NodeType::Phantom => false, - } - } +/// Enum representing node of a trace of a call. +#[derive(Clone)] +pub enum CallTraceNode { + EntryPointCall(Rc>), + DeployWithoutConstructor, } #[derive(Clone)] @@ -417,7 +406,7 @@ impl TraceData { current_call .borrow_mut() .nested_calls - .push(new_call.clone()); + .push(CallTraceNode::EntryPointCall(new_call.clone())); self.current_call_stack .push(new_call, resources_used_before_call, cheated_data); @@ -456,14 +445,13 @@ impl TraceData { last_call.vm_trace = vm_trace; } - pub fn add_phantom_call(&mut self) { - let new_call = Rc::new(RefCell::new(CallTrace { - node_type: NodeType::Phantom, - ..Default::default() - })); + pub fn add_deploy_without_constructor_node(&mut self) { let current_call = self.current_call_stack.top(); - current_call.borrow_mut().nested_calls.push(new_call); + current_call + .borrow_mut() + .nested_calls + .push(CallTraceNode::DeployWithoutConstructor); } } diff --git a/crates/forge-runner/src/build_trace_data.rs b/crates/forge-runner/src/build_trace_data.rs index 671e7c532f..7456ec41db 100644 --- a/crates/forge-runner/src/build_trace_data.rs +++ b/crates/forge-runner/src/build_trace_data.rs @@ -12,7 +12,7 @@ use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use cairo_vm::vm::trace::trace_entry::TraceEntry; use cheatnet::constants::{TEST_CONTRACT_CLASS_HASH, TEST_ENTRY_POINT_SELECTOR}; use cheatnet::runtime_extensions::forge_runtime_extension::contracts_data::ContractsData; -use cheatnet::state::{CallTrace, NodeType}; +use cheatnet::state::{CallTrace, CallTraceNode}; use conversions::IntoConv; use itertools::Itertools; use starknet::core::utils::get_selector_from_name; @@ -22,10 +22,10 @@ use starknet_api::deprecated_contract_class::EntryPointType; use starknet_api::hash::StarkHash; use trace_data::{ CallEntryPoint as ProfilerCallEntryPoint, CallTrace as ProfilerCallTrace, - CallType as ProfilerCallType, ContractAddress, + CallTraceNode as ProfilerCallTraceNode, CallType as ProfilerCallType, ContractAddress, DeprecatedSyscallSelector as ProfilerDeprecatedSyscallSelector, EntryPointSelector, EntryPointType as ProfilerEntryPointType, ExecutionResources as ProfilerExecutionResources, - NodeType as ProfilerNodeType, TraceEntry as ProfilerTraceEntry, VmExecutionResources, + TraceEntry as ProfilerTraceEntry, VmExecutionResources, }; pub const TRACE_DIR: &str = ".snfoundry_trace"; @@ -55,10 +55,21 @@ pub fn build_profiler_call_trace( nested_calls: value .nested_calls .iter() - .map(|c| build_profiler_call_trace(c, contracts_data)) + .map(|c| build_profiler_call_trace_node(c, contracts_data)) .collect(), vm_trace, - node_type: build_profiler_node_type(value.node_type), + } +} + +fn build_profiler_call_trace_node( + value: &CallTraceNode, + contracts_data: &ContractsData, +) -> ProfilerCallTraceNode { + match value { + CallTraceNode::EntryPointCall(trace) => { + ProfilerCallTraceNode::EntryPointCall(build_profiler_call_trace(trace, contracts_data)) + } + CallTraceNode::DeployWithoutConstructor => ProfilerCallTraceNode::DeployWithoutConstructor, } } @@ -212,13 +223,6 @@ fn build_profiler_trace_entry(value: &TraceEntry) -> ProfilerTraceEntry { } } -fn build_profiler_node_type(value: NodeType) -> ProfilerNodeType { - match value { - NodeType::Regular => ProfilerNodeType::Regular, - NodeType::Phantom => ProfilerNodeType::Phantom, - } -} - pub fn save_trace_data(test_name: &String, trace_data: &ProfilerCallTrace) -> Result { let serialized_trace = serde_json::to_string(trace_data).expect("Failed to serialize call trace"); diff --git a/crates/forge/tests/e2e/build_trace_data.rs b/crates/forge/tests/e2e/build_trace_data.rs index b7d37b8b09..9830d3c435 100644 --- a/crates/forge/tests/e2e/build_trace_data.rs +++ b/crates/forge/tests/e2e/build_trace_data.rs @@ -1,7 +1,8 @@ use super::common::runner::{setup_package, test_runner}; +use crate::e2e::common::get_trace_from_trace_node; use forge_runner::build_trace_data::{TEST_CODE_CONTRACT_NAME, TEST_CODE_FUNCTION_NAME, TRACE_DIR}; use std::fs; -use trace_data::{CallTrace as ProfilerCallTrace, NodeType}; +use trace_data::{CallTrace as ProfilerCallTrace, CallTraceNode as ProfilerCallTraceNode}; #[test] fn simple_package_save_trace() { @@ -65,7 +66,7 @@ fn trace_has_contract_and_function_names() { call_trace.entry_point.function_name, Some(String::from(TEST_CODE_FUNCTION_NAME)) ); - assert_contract_and_function_names(&call_trace.nested_calls[3]); + assert_contract_and_function_names(get_trace_from_trace_node(&call_trace.nested_calls[3])); } fn assert_contract_and_function_names(trace: &ProfilerCallTrace) { @@ -79,8 +80,8 @@ fn assert_contract_and_function_names(trace: &ProfilerCallTrace) { Some(String::from("execute_calls")) ); - for sub_trace in &trace.nested_calls { - assert_contract_and_function_names(sub_trace); + for sub_trace_node in &trace.nested_calls { + assert_contract_and_function_names(get_trace_from_trace_node(sub_trace_node)); } } @@ -109,13 +110,13 @@ fn trace_has_vm_trace() { fn assert_vm_trace_exists(trace: &ProfilerCallTrace) { assert!( - trace.vm_trace.is_some() - || trace.entry_point.function_name == Some(String::from("fail")) - || matches!(trace.node_type, NodeType::Phantom) + trace.vm_trace.is_some() || trace.entry_point.function_name == Some(String::from("fail")) ); - for sub_trace in &trace.nested_calls { - assert_vm_trace_exists(sub_trace); + for sub_trace_node in &trace.nested_calls { + if let ProfilerCallTraceNode::EntryPointCall(sub_trace) = sub_trace_node { + assert_vm_trace_exists(sub_trace); + } } } @@ -140,7 +141,16 @@ fn trace_has_deploy_with_no_constructor_phantom_nodes() { serde_json::from_str(&trace_data).expect("Failed to parse call_trace"); // 3 first calls are deploys with empty constructors - matches!(call_trace.nested_calls[0].node_type, NodeType::Phantom); - matches!(call_trace.nested_calls[1].node_type, NodeType::Phantom); - matches!(call_trace.nested_calls[2].node_type, NodeType::Phantom); + matches!( + call_trace.nested_calls[0], + trace_data::CallTraceNode::DeployWithoutConstructor + ); + matches!( + call_trace.nested_calls[1], + trace_data::CallTraceNode::DeployWithoutConstructor + ); + matches!( + call_trace.nested_calls[2], + trace_data::CallTraceNode::DeployWithoutConstructor + ); } diff --git a/crates/forge/tests/e2e/common/mod.rs b/crates/forge/tests/e2e/common/mod.rs index 748377a9c8..575b63a851 100644 --- a/crates/forge/tests/e2e/common/mod.rs +++ b/crates/forge/tests/e2e/common/mod.rs @@ -1 +1,11 @@ +use trace_data::{CallTrace as ProfilerCallTrace, CallTraceNode as ProfilerCallTraceNode}; + pub mod runner; + +pub fn get_trace_from_trace_node(trace_node: &ProfilerCallTraceNode) -> &ProfilerCallTrace { + if let ProfilerCallTraceNode::EntryPointCall(trace) = trace_node { + trace + } else { + panic!("Deploy without constructor node was not expected") + } +} diff --git a/crates/forge/tests/e2e/trace_resources.rs b/crates/forge/tests/e2e/trace_resources.rs index 5e0ea38ecc..e14067106b 100644 --- a/crates/forge/tests/e2e/trace_resources.rs +++ b/crates/forge/tests/e2e/trace_resources.rs @@ -1,9 +1,10 @@ use super::common::runner::{setup_package, test_runner}; +use crate::e2e::common::get_trace_from_trace_node; use assert_fs::TempDir; use forge_runner::build_trace_data::TRACE_DIR; use std::{collections::HashMap, fs}; use trace_data::{ - CallTrace as ProfilerCallTrace, + CallTrace as ProfilerCallTrace, CallTraceNode as ProfilerCallTraceNode, DeprecatedSyscallSelector::{ CallContract, Deploy, EmitEvent, GetBlockHash, GetExecutionInfo, Keccak, LibraryCall, SendMessageToL1, StorageRead, StorageWrite, @@ -75,8 +76,8 @@ fn check_vm_resources_and_easily_unifiable_syscalls( call_trace: &ProfilerCallTrace, ) -> &ProfilerExecutionResources { let mut child_resources = vec![]; - for call in &call_trace.nested_calls { - if matches!(call.node_type, trace_data::NodeType::Regular) { + for call_node in &call_trace.nested_calls { + if let trace_data::CallTraceNode::EntryPointCall(call) = call_node { child_resources.push(check_vm_resources_and_easily_unifiable_syscalls(call)); } } @@ -154,39 +155,39 @@ fn assert_l2_l1_messages(call_trace: &ProfilerCallTrace) { fn check_call(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 14, 8, 1); - let regular_call = &test_call_trace.nested_calls[4]; + let regular_call = get_trace_from_trace_node(&test_call_trace.nested_calls[4]); assert_not_easily_unifiable_syscalls(regular_call, 2, 1, 0); - let from_proxy = ®ular_call.nested_calls[1]; + let from_proxy = get_trace_from_trace_node(®ular_call.nested_calls[1]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let with_libcall = &test_call_trace.nested_calls[5]; + let with_libcall = get_trace_from_trace_node(&test_call_trace.nested_calls[5]); assert_not_easily_unifiable_syscalls(with_libcall, 2, 0, 1); - let from_proxy = &with_libcall.nested_calls[1]; + let from_proxy = get_trace_from_trace_node(&with_libcall.nested_calls[1]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let call_two = &test_call_trace.nested_calls[6]; + let call_two = get_trace_from_trace_node(&test_call_trace.nested_calls[6]); assert_not_easily_unifiable_syscalls(call_two, 3, 2, 0); - let from_proxy = &call_two.nested_calls[0]; + let from_proxy = get_trace_from_trace_node(&call_two.nested_calls[0]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let from_proxy_dummy = &call_two.nested_calls[2]; + let from_proxy_dummy = get_trace_from_trace_node(&call_two.nested_calls[2]); assert_not_easily_unifiable_syscalls(from_proxy_dummy, 1, 0, 0); - let from_proxy = &test_call_trace.nested_calls[7]; + let from_proxy = get_trace_from_trace_node(&test_call_trace.nested_calls[7]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); } fn check_deploy(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 14, 4, 0); - for deploy_proxy in &test_call_trace.nested_calls { - if matches!(deploy_proxy.node_type, trace_data::NodeType::Regular) { + for deploy_proxy_node in &test_call_trace.nested_calls { + if let ProfilerCallTraceNode::EntryPointCall(deploy_proxy) = deploy_proxy_node { assert_not_easily_unifiable_syscalls(deploy_proxy, 2, 1, 0); - let from_proxy = &deploy_proxy.nested_calls[1]; + let from_proxy = get_trace_from_trace_node(&deploy_proxy.nested_calls[1]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); } } @@ -195,38 +196,39 @@ fn check_deploy(test_call_trace: &ProfilerCallTrace) { fn check_l1_handler(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 8, 3, 0); - let handle_l1 = &test_call_trace.nested_calls[3]; + let handle_l1 = get_trace_from_trace_node(&test_call_trace.nested_calls[3]); assert_not_easily_unifiable_syscalls(handle_l1, 3, 2, 0); - let regular_call = &handle_l1.nested_calls[1]; + let regular_call = get_trace_from_trace_node(&handle_l1.nested_calls[1]); assert_not_easily_unifiable_syscalls(regular_call, 2, 1, 0); - let from_proxy = ®ular_call.nested_calls[1]; + let from_proxy = get_trace_from_trace_node(®ular_call.nested_calls[1]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); } fn check_libcall(test_call_trace: &ProfilerCallTrace) { assert_not_easily_unifiable_syscalls(test_call_trace, 11, 3, 5); - let regular_call = &test_call_trace.nested_calls[3]; + let regular_call = get_trace_from_trace_node(&test_call_trace.nested_calls[3]); + assert_not_easily_unifiable_syscalls(regular_call, 2, 1, 0); - let from_proxy = ®ular_call.nested_calls[1]; + let from_proxy = get_trace_from_trace_node(®ular_call.nested_calls[1]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let with_libcall = &test_call_trace.nested_calls[4]; + let with_libcall = get_trace_from_trace_node(&test_call_trace.nested_calls[4]); assert_not_easily_unifiable_syscalls(with_libcall, 2, 0, 1); - let call_two = &test_call_trace.nested_calls[5]; + let call_two = get_trace_from_trace_node(&test_call_trace.nested_calls[5]); assert_not_easily_unifiable_syscalls(call_two, 3, 2, 0); - let from_proxy = &call_two.nested_calls[0]; + let from_proxy = get_trace_from_trace_node(&call_two.nested_calls[0]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); - let from_proxy_dummy = &call_two.nested_calls[2]; + let from_proxy_dummy = get_trace_from_trace_node(&call_two.nested_calls[2]); assert_not_easily_unifiable_syscalls(from_proxy_dummy, 1, 0, 0); - let from_proxy = &test_call_trace.nested_calls[6]; + let from_proxy = get_trace_from_trace_node(&test_call_trace.nested_calls[6]); assert_not_easily_unifiable_syscalls(from_proxy, 1, 0, 0); } From 975a491f76c31f335b80705cde28fdbc0c9ec9bd Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Mon, 8 Apr 2024 15:51:52 +0200 Subject: [PATCH 07/12] stylistic changes --- .../forge_runtime_extension/mod.rs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs index d68559e48a..f1677ebb10 100644 --- a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs +++ b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs @@ -687,17 +687,22 @@ fn handle_deploy_result( fn serialize_call_trace(call_trace: &CallTrace, output: &mut Vec) { serialize_call_entry_point(&call_trace.entry_point, output); - let visible_calls_count = call_trace + let visible_calls: Vec<_> = call_trace .nested_calls .iter() - .filter(|call| matches!(call, CallTraceNode::EntryPointCall(_))) - .count(); - output.push(Felt252::from(visible_calls_count)); + .filter_map(|call_node| { + if let CallTraceNode::EntryPointCall(call) = call_node { + Some(call) + } else { + None + } + }) + .collect(); - for call_trace_node in &call_trace.nested_calls { - if let CallTraceNode::EntryPointCall(call_trace) = call_trace_node { - serialize_call_trace(&call_trace.borrow(), output); - } + output.push(Felt252::from(visible_calls.len())); + + for call_trace_node in visible_calls { + serialize_call_trace(&call_trace_node.borrow(), output); } serialize_call_result(&call_trace.result, output); From 4a7f04f29e088f04d38df4307ae5e03a679b819e Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Mon, 8 Apr 2024 16:35:53 +0200 Subject: [PATCH 08/12] stylistic changes --- .../call_to_blockifier_runtime_extension/rpc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs index d7f62923ca..b07a9c1ac2 100644 --- a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs +++ b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs @@ -41,7 +41,7 @@ pub enum CallResult { impl Default for CallResult { fn default() -> Self { - Self::Success { ret_data: vec![] } + Self::Failure(CallFailure::Error { msg: String::new() }) } } From d30476e514a08134a90631f4f695d9b0dc0db5cb Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Mon, 8 Apr 2024 17:25:37 +0200 Subject: [PATCH 09/12] fix stuff --- .../call_to_blockifier_runtime_extension/rpc.rs | 2 +- .../src/runtime_extensions/forge_runtime_extension/mod.rs | 2 +- crates/cheatnet/src/state.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs index b07a9c1ac2..9c47387677 100644 --- a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs +++ b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs @@ -45,7 +45,7 @@ impl Default for CallResult { } } -/// Enum representing possible call failure and its' type. +/// Enum representing possible call failure and its type. /// `Panic` - Recoverable, meant to be caught by the user. /// `Error` - Unrecoverable, equivalent of panic! in rust. #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs index f1677ebb10..16c6dd3509 100644 --- a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs +++ b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs @@ -750,7 +750,7 @@ fn serialize_call_result(call_result: &CallResult, output: &mut Vec) { serialize_failure_data(0, panic_data.iter().cloned(), panic_data.len(), output); } CallFailure::Error { msg } => { - let data = ByteArray::from(msg.as_str()).serialize_with_magic(); + let data = ByteArray::from(msg.as_str()).serialize_no_magic(); let len = data.len(); serialize_failure_data(1, data, len, output); } diff --git a/crates/cheatnet/src/state.rs b/crates/cheatnet/src/state.rs index 71521f6ea6..4971ac7a31 100644 --- a/crates/cheatnet/src/state.rs +++ b/crates/cheatnet/src/state.rs @@ -267,6 +267,7 @@ impl Default for CheatnetState { test_code_entry_point.class_hash = Some(class_hash!(TEST_CONTRACT_CLASS_HASH)); let test_call = Rc::new(RefCell::new(CallTrace { entry_point: test_code_entry_point, + result: CallResult::Success { ret_data: vec![] }, ..Default::default() })); Self { From e1b98ab112b19a5dbedab2afeefded8e12282f65 Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Mon, 8 Apr 2024 17:42:59 +0200 Subject: [PATCH 10/12] ignore build profile test --- Cargo.lock | 2 +- Cargo.toml | 2 +- crates/forge/tests/e2e/build_profile.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9157617e4f..e68b0060d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5263,7 +5263,7 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "trace-data" version = "0.2.0" -source = "git+https://github.com/software-mansion/cairo-profiler/?rev=8e3fa5b418b655acfa6c07c90cf5ccf7c297c381#8e3fa5b418b655acfa6c07c90cf5ccf7c297c381" +source = "git+https://github.com/software-mansion/cairo-profiler/?rev=0b9dafb#0b9dafbfdcc9237904738fece4e6c054323b528d" dependencies = [ "serde", ] diff --git a/Cargo.toml b/Cargo.toml index eca057ddb8..a88f0c4b32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,7 +62,7 @@ regex = "1.10.4" serde = { version = "1.0.197", features = ["derive"] } serde_json = "1.0.115" starknet = { git = "https://github.com/xJonathanLEI/starknet-rs", rev = "d980869" } -trace-data = { git = "https://github.com/software-mansion/cairo-profiler/", rev = "8e3fa5b418b655acfa6c07c90cf5ccf7c297c381" } +trace-data = { git = "https://github.com/software-mansion/cairo-profiler/", rev = "0b9dafb" } tempfile = "3.10.1" thiserror = "1.0.58" ctor = "0.2.7" diff --git a/crates/forge/tests/e2e/build_profile.rs b/crates/forge/tests/e2e/build_profile.rs index 6b60af0550..2d83025d91 100644 --- a/crates/forge/tests/e2e/build_profile.rs +++ b/crates/forge/tests/e2e/build_profile.rs @@ -2,6 +2,7 @@ use super::common::runner::{setup_package, test_runner}; use forge_runner::profiler_api::PROFILE_DIR; #[test] +#[ignore] // TODO(#1991): remove ignore when new profiler is released fn simple_package_build_profile() { let temp = setup_package("simple_package"); From 7554386efaf1aad92a11478d9563bce1e712509d Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Wed, 10 Apr 2024 18:23:26 +0200 Subject: [PATCH 11/12] changes --- .../forge_runtime_extension/mod.rs | 16 ++-------------- crates/cheatnet/src/state.rs | 11 +++++++++++ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs index 16c6dd3509..d0b5696712 100644 --- a/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs +++ b/crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs @@ -690,13 +690,7 @@ fn serialize_call_trace(call_trace: &CallTrace, output: &mut Vec) { let visible_calls: Vec<_> = call_trace .nested_calls .iter() - .filter_map(|call_node| { - if let CallTraceNode::EntryPointCall(call) = call_node { - Some(call) - } else { - None - } - }) + .filter_map(CallTraceNode::extract_entry_point_call) .collect(); output.push(Felt252::from(visible_calls.len())); @@ -833,13 +827,7 @@ pub fn update_top_call_execution_resources(runtime: &mut ForgeRuntime) { let nested_calls_syscalls = top_call .nested_calls .iter() - .filter_map(|trace_node| { - if let CallTraceNode::EntryPointCall(trace) = trace_node { - Some(trace) - } else { - None - } - }) + .filter_map(CallTraceNode::extract_entry_point_call) .fold(SyscallCounter::new(), |syscalls, trace| { sum_syscall_counters(syscalls, &trace.borrow().used_syscalls) }); diff --git a/crates/cheatnet/src/state.rs b/crates/cheatnet/src/state.rs index 4971ac7a31..b4fb15f825 100644 --- a/crates/cheatnet/src/state.rs +++ b/crates/cheatnet/src/state.rs @@ -168,6 +168,17 @@ pub enum CallTraceNode { DeployWithoutConstructor, } +impl CallTraceNode { + #[must_use] + pub fn extract_entry_point_call(&self) -> Option<&Rc>> { + if let CallTraceNode::EntryPointCall(trace) = self { + Some(trace) + } else { + None + } + } +} + #[derive(Clone)] struct CallStackElement { // when we exit the call we use it to calculate resources used by the call From 4d5cb9b3d2710d4229e3d67e7f0c3f1d03cb5403 Mon Sep 17 00:00:00 2001 From: Piotr Magiera Date: Wed, 10 Apr 2024 18:26:38 +0200 Subject: [PATCH 12/12] change default to func --- .../rpc.rs | 6 ------ crates/cheatnet/src/state.rs | 20 +++++++++++++++---- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs index 9c47387677..2dab9df2f8 100644 --- a/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs +++ b/crates/cheatnet/src/runtime_extensions/call_to_blockifier_runtime_extension/rpc.rs @@ -39,12 +39,6 @@ pub enum CallResult { Failure(CallFailure), } -impl Default for CallResult { - fn default() -> Self { - Self::Failure(CallFailure::Error { msg: String::new() }) - } -} - /// Enum representing possible call failure and its type. /// `Panic` - Recoverable, meant to be caught by the user. /// `Error` - Unrecoverable, equivalent of panic! in rust. diff --git a/crates/cheatnet/src/state.rs b/crates/cheatnet/src/state.rs index b4fb15f825..58265c84ba 100644 --- a/crates/cheatnet/src/state.rs +++ b/crates/cheatnet/src/state.rs @@ -149,7 +149,6 @@ impl CheatStatus { } /// Tree structure representing trace of a call. -#[derive(Default)] pub struct CallTrace { pub entry_point: CallEntryPoint, // These also include resources used by internal calls @@ -161,6 +160,20 @@ pub struct CallTrace { pub vm_trace: Option>, } +impl CallTrace { + fn default_successful_call() -> Self { + Self { + entry_point: Default::default(), + used_execution_resources: Default::default(), + used_l1_resources: Default::default(), + used_syscalls: Default::default(), + nested_calls: vec![], + result: CallResult::Success { ret_data: vec![] }, + vm_trace: None, + } + } +} + /// Enum representing node of a trace of a call. #[derive(Clone)] pub enum CallTraceNode { @@ -278,8 +291,7 @@ impl Default for CheatnetState { test_code_entry_point.class_hash = Some(class_hash!(TEST_CONTRACT_CLASS_HASH)); let test_call = Rc::new(RefCell::new(CallTrace { entry_point: test_code_entry_point, - result: CallResult::Success { ret_data: vec![] }, - ..Default::default() + ..CallTrace::default_successful_call() })); Self { rolled_contracts: Default::default(), @@ -411,7 +423,7 @@ impl TraceData { ) { let new_call = Rc::new(RefCell::new(CallTrace { entry_point, - ..Default::default() + ..CallTrace::default_successful_call() })); let current_call = self.current_call_stack.top();