Skip to content

Commit 76acf69

Browse files
authored
Store execution summary in trace data (#3794)
<!-- Reference any GitHub issues resolved by this PR --> Related #3660
1 parent 012a0d3 commit 76acf69

File tree

3 files changed

+87
-6
lines changed

3 files changed

+87
-6
lines changed

crates/cheatnet/src/runtime_extensions/forge_runtime_extension/mod.rs

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@ use crate::runtime_extensions::{
1717
storage::{calculate_variable_address, load, store},
1818
},
1919
};
20-
use crate::state::{CallTrace, CallTraceNode};
20+
use crate::state::{CallTrace, CallTraceNode, GasReportData};
2121
use anyhow::{Context, Result, anyhow};
2222
use blockifier::bouncer::vm_resources_to_sierra_gas;
2323
use blockifier::context::TransactionContext;
24-
use blockifier::execution::call_info::CallInfo;
24+
use blockifier::execution::call_info::{
25+
CallInfo, CallSummary, ChargedResources, EventSummary, ExecutionSummary, OrderedEvent,
26+
};
2527
use blockifier::execution::contract_class::TrackedResource;
2628
use blockifier::execution::syscalls::vm_syscall_utils::{SyscallSelector, SyscallUsageMap};
2729
use blockifier::state::errors::StateError;
30+
use blockifier::utils::u64_from_usize;
2831
use cairo_vm::vm::runners::cairo_runner::CairoRunner;
2932
use cairo_vm::vm::{
3033
errors::hint_errors::HintError, runners::cairo_runner::ExecutionResources,
@@ -42,10 +45,11 @@ use runtime::{
4245
};
4346
use scarb_oracle_hint_service::OracleHintService;
4447
use starknet::signers::SigningKey;
48+
use starknet_api::execution_resources::GasAmount;
4549
use starknet_api::{contract_class::EntryPointType::L1Handler, core::ClassHash};
4650
use starknet_types_core::felt::Felt;
4751
use std::cell::RefCell;
48-
use std::collections::HashMap;
52+
use std::collections::{HashMap, HashSet};
4953
use std::rc::Rc;
5054
use std::sync::{Arc, Mutex};
5155

@@ -738,6 +742,65 @@ pub fn update_top_call_vm_trace(runtime: &mut ForgeRuntime, cairo_runner: &mut C
738742
}
739743
}
740744

745+
pub fn compute_and_store_execution_summary(trace: &Rc<RefCell<CallTrace>>) {
746+
let execution_summary = if trace.borrow().nested_calls.is_empty() {
747+
get_execution_summary_without_nested_calls(trace)
748+
} else {
749+
let mut nested_calls_summaries = vec![];
750+
for nested_call in &trace.borrow().nested_calls {
751+
if let CallTraceNode::EntryPointCall(nested_call) = nested_call {
752+
compute_and_store_execution_summary(nested_call);
753+
nested_calls_summaries.push(
754+
nested_call
755+
.borrow()
756+
.gas_report_data
757+
.as_ref()
758+
.expect("Gas report data must be set after calling `compute_and_store_execution_summary`")
759+
.execution_summary
760+
.clone());
761+
}
762+
}
763+
let mut current_call_summary = get_execution_summary_without_nested_calls(trace)
764+
+ nested_calls_summaries.into_iter().sum();
765+
766+
// vm_resources and gas_consumed of a call already contain the resources of its inner calls.
767+
current_call_summary.charged_resources.vm_resources =
768+
trace.borrow().used_execution_resources.clone();
769+
current_call_summary.charged_resources.gas_consumed =
770+
GasAmount(trace.borrow().gas_consumed);
771+
current_call_summary
772+
};
773+
774+
trace.borrow_mut().gas_report_data = Some(GasReportData::new(execution_summary.clone()));
775+
}
776+
777+
// Based on blockifier/src/execution/call_info.rs (summarize)
778+
fn get_execution_summary_without_nested_calls(trace: &Rc<RefCell<CallTrace>>) -> ExecutionSummary {
779+
let current_call = trace.borrow();
780+
ExecutionSummary {
781+
charged_resources: ChargedResources {
782+
vm_resources: current_call.used_execution_resources.clone(),
783+
gas_consumed: GasAmount(current_call.gas_consumed),
784+
},
785+
l2_to_l1_payload_lengths: current_call.used_l1_resources.l2_l1_message_sizes.clone(),
786+
event_summary: {
787+
let mut event_summary = EventSummary {
788+
n_events: current_call.events.len(),
789+
..Default::default()
790+
};
791+
for OrderedEvent { event, .. } in &current_call.events {
792+
event_summary.total_event_data_size += u64_from_usize(event.data.0.len());
793+
event_summary.total_event_keys += u64_from_usize(event.keys.len());
794+
}
795+
event_summary
796+
},
797+
// Fields below are not relevant for partial gas calculation.
798+
call_summary: CallSummary::default(),
799+
executed_class_hashes: HashSet::default(),
800+
visited_storage_entries: HashSet::default(),
801+
}
802+
}
803+
741804
fn add_sierra_gas_resources(top_call: &Rc<RefCell<CallTrace>>) -> u64 {
742805
let mut gas_consumed = top_call.borrow().gas_consumed;
743806
for nested_call in &top_call.borrow().nested_calls {

crates/cheatnet/src/state.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::runtime_extensions::forge_runtime_extension::cheatcodes::cheat_execut
1010
};
1111
use crate::runtime_extensions::forge_runtime_extension::cheatcodes::spy_events::Event;
1212
use crate::runtime_extensions::forge_runtime_extension::cheatcodes::spy_messages_to_l1::MessageToL1;
13-
use blockifier::execution::call_info::{OrderedEvent, OrderedL2ToL1Message};
13+
use blockifier::execution::call_info::{ExecutionSummary, OrderedEvent, OrderedL2ToL1Message};
1414
use blockifier::execution::contract_class::RunnableCompiledClass;
1515
use blockifier::execution::entry_point::CallEntryPoint;
1616
use blockifier::execution::syscalls::vm_syscall_utils::SyscallUsageMap;
@@ -203,6 +203,18 @@ impl<T> CheatStatus<T> {
203203
}
204204
}
205205

206+
#[derive(Debug)]
207+
pub struct GasReportData {
208+
pub execution_summary: ExecutionSummary,
209+
}
210+
211+
impl GasReportData {
212+
#[must_use]
213+
pub fn new(execution_summary: ExecutionSummary) -> Self {
214+
Self { execution_summary }
215+
}
216+
}
217+
206218
/// Tree structure representing trace of a call.
207219
#[derive(Debug)]
208220
pub struct CallTrace {
@@ -221,6 +233,9 @@ pub struct CallTrace {
221233
pub gas_consumed: u64,
222234
pub events: Vec<OrderedEvent>,
223235
pub signature: Vec<Felt>,
236+
237+
// This is updated only once after the entire test execution.
238+
pub gas_report_data: Option<GasReportData>,
224239
}
225240

226241
impl CairoSerialize for CallTrace {
@@ -253,6 +268,7 @@ impl CallTrace {
253268
gas_consumed: u64::default(),
254269
events: vec![],
255270
signature: vec![],
271+
gas_report_data: None,
256272
}
257273
}
258274

crates/forge-runner/src/running.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ use cheatnet::runtime_extensions::call_to_blockifier_runtime_extension::CallToBl
2323
use cheatnet::runtime_extensions::call_to_blockifier_runtime_extension::rpc::UsedResources;
2424
use cheatnet::runtime_extensions::cheatable_starknet_runtime_extension::CheatableStarknetRuntimeExtension;
2525
use cheatnet::runtime_extensions::forge_runtime_extension::{
26-
ForgeExtension, ForgeRuntime, add_resources_to_top_call, get_all_used_resources,
27-
update_top_call_l1_resources, update_top_call_resources, update_top_call_vm_trace,
26+
ForgeExtension, ForgeRuntime, add_resources_to_top_call, compute_and_store_execution_summary,
27+
get_all_used_resources, update_top_call_l1_resources, update_top_call_resources,
28+
update_top_call_vm_trace,
2829
};
2930
use cheatnet::state::{
3031
BlockInfoReader, CallTrace, CheatnetState, EncounteredErrors, ExtendedStateReader,
@@ -332,6 +333,7 @@ pub fn run_test_case(
332333

333334
update_top_call_resources(&mut forge_runtime, tracked_resource);
334335
update_top_call_l1_resources(&mut forge_runtime);
336+
compute_and_store_execution_summary(&call_trace_ref);
335337

336338
let fuzzer_args = forge_runtime
337339
.extended_runtime

0 commit comments

Comments
 (0)