diff --git a/crates/executor/src/estimate.rs b/crates/executor/src/estimate.rs index fc3663f746..0580a4b87e 100644 --- a/crates/executor/src/estimate.rs +++ b/crates/executor/src/estimate.rs @@ -1,6 +1,5 @@ use blockifier::transaction::transaction_execution::Transaction; use blockifier::transaction::transactions::ExecutableTransaction; -use starknet_api::transaction::fields::GasVectorComputationMode; use super::error::TransactionExecutionError; use super::execution_state::ExecutionState; @@ -19,12 +18,14 @@ pub fn estimate( let _span = tracing::debug_span!("estimate", transaction_hash=%super::transaction::transaction_hash(&transaction), %block_number, %transaction_idx).entered(); let fee_type = super::transaction::fee_type(&transaction); + let gas_vector_computation_mode = + super::transaction::gas_vector_computation_mode(&transaction); let minimal_l1_gas_amount_vector = match &transaction { Transaction::Account(account_transaction) => { Some(blockifier::fee::gas_usage::estimate_minimal_gas_vector( &block_context, account_transaction, - &GasVectorComputationMode::All, + &gas_vector_computation_mode, )) } Transaction::L1Handler(_) => None, diff --git a/crates/executor/src/simulate.rs b/crates/executor/src/simulate.rs index 390cb6398c..823afe231b 100644 --- a/crates/executor/src/simulate.rs +++ b/crates/executor/src/simulate.rs @@ -94,12 +94,15 @@ pub fn simulate( let transaction_declared_deprecated_class_hash = transaction_declared_deprecated_class(&transaction); let fee_type = super::transaction::fee_type(&transaction); + let gas_vector_computation_mode = + super::transaction::gas_vector_computation_mode(&transaction); + let minimal_l1_gas_amount_vector = match &transaction { Transaction::Account(account_transaction) => { Some(blockifier::fee::gas_usage::estimate_minimal_gas_vector( &block_context, account_transaction, - &GasVectorComputationMode::All, + &gas_vector_computation_mode, )) } Transaction::L1Handler(_) => None, @@ -131,6 +134,7 @@ pub fn simulate( tx_info, state_diff, block_context.versioned_constants(), + &gas_vector_computation_mode, ), }); } @@ -186,6 +190,7 @@ pub fn trace( let tx_type = transaction_type(&tx); let tx_declared_deprecated_class_hash = transaction_declared_deprecated_class(&tx); + let gas_vector_computation_mode = super::transaction::gas_vector_computation_mode(&tx); let mut tx_state = CachedState::<_>::create_transactional(&mut state); let tx_info = tx.execute(&mut tx_state, &block_context).map_err(|e| { @@ -216,6 +221,7 @@ pub fn trace( tx_info, state_diff, block_context.versioned_constants(), + &gas_vector_computation_mode, ); traces.push((hash, trace)); } @@ -364,16 +370,29 @@ fn to_trace( execution_info: blockifier::transaction::objects::TransactionExecutionInfo, state_diff: StateDiff, versioned_constants: &VersionedConstants, + gas_vector_computation_mode: &GasVectorComputationMode, ) -> TransactionTrace { - let validate_invocation = execution_info - .validate_call_info - .map(|call_info| FunctionInvocation::from_call_info(call_info, versioned_constants)); - let maybe_function_invocation = execution_info - .execute_call_info - .map(|call_info| FunctionInvocation::from_call_info(call_info, versioned_constants)); - let fee_transfer_invocation = execution_info - .fee_transfer_call_info - .map(|call_info| FunctionInvocation::from_call_info(call_info, versioned_constants)); + let validate_invocation = execution_info.validate_call_info.map(|call_info| { + FunctionInvocation::from_call_info( + call_info, + versioned_constants, + gas_vector_computation_mode, + ) + }); + let maybe_function_invocation = execution_info.execute_call_info.map(|call_info| { + FunctionInvocation::from_call_info( + call_info, + versioned_constants, + gas_vector_computation_mode, + ) + }); + let fee_transfer_invocation = execution_info.fee_transfer_call_info.map(|call_info| { + FunctionInvocation::from_call_info( + call_info, + versioned_constants, + gas_vector_computation_mode, + ) + }); let computation_resources = validate_invocation .as_ref() diff --git a/crates/executor/src/transaction.rs b/crates/executor/src/transaction.rs index 07b16a0109..86fbd3e139 100644 --- a/crates/executor/src/transaction.rs +++ b/crates/executor/src/transaction.rs @@ -2,6 +2,7 @@ use blockifier::transaction::objects::HasRelatedFeeType; use blockifier::transaction::transaction_execution::Transaction; use pathfinder_common::TransactionHash; use starknet_api::block::FeeType; +use starknet_api::transaction::fields::GasVectorComputationMode; use super::felt::IntoFelt; @@ -34,3 +35,41 @@ pub fn fee_type(transaction: &Transaction) -> FeeType { Transaction::L1Handler(tx) => tx.fee_type(), } } + +pub fn gas_vector_computation_mode(transaction: &Transaction) -> GasVectorComputationMode { + match &transaction { + Transaction::Account(account_transaction) => { + use starknet_api::executable_transaction::AccountTransaction; + match &account_transaction.tx { + AccountTransaction::Declare(tx) => { + use starknet_api::transaction::DeclareTransaction; + match &tx.tx { + DeclareTransaction::V3(tx) => { + tx.resource_bounds.get_gas_vector_computation_mode() + } + _ => GasVectorComputationMode::NoL2Gas, + } + } + AccountTransaction::DeployAccount(tx) => { + use starknet_api::transaction::DeployAccountTransaction; + match &tx.tx { + DeployAccountTransaction::V3(tx) => { + tx.resource_bounds.get_gas_vector_computation_mode() + } + _ => GasVectorComputationMode::NoL2Gas, + } + } + AccountTransaction::Invoke(tx) => { + use starknet_api::transaction::InvokeTransaction; + match &tx.tx { + InvokeTransaction::V3(tx) => { + tx.resource_bounds.get_gas_vector_computation_mode() + } + _ => GasVectorComputationMode::NoL2Gas, + } + } + } + } + Transaction::L1Handler(_) => GasVectorComputationMode::NoL2Gas, + } +} diff --git a/crates/executor/src/types.rs b/crates/executor/src/types.rs index 7a156e6444..311f2d4615 100644 --- a/crates/executor/src/types.rs +++ b/crates/executor/src/types.rs @@ -1,7 +1,6 @@ use std::collections::{BTreeMap, HashSet}; use blockifier::execution::call_info::OrderedL2ToL1Message; -use blockifier::fee::fee_utils::get_vm_resources_cost; use blockifier::transaction::objects::TransactionExecutionInfo; use pathfinder_common::{ CasmHash, @@ -313,17 +312,135 @@ pub struct DataAvailabilityResources { pub l1_data_gas: u128, } +// Non-recursive variant of `CallInfo::summarize()` +fn summarize_call_info( + call_info: &blockifier::execution::call_info::CallInfo, +) -> blockifier::execution::call_info::ExecutionSummary { + let class_hash = call_info + .call + .class_hash + .expect("Class hash must be set after execution."); + let executed_class_hashes: HashSet = + std::iter::once(class_hash).collect(); + + // Storage entries. + let visited_storage_entries = call_info + .accessed_storage_keys + .iter() + .map(|storage_key| (call_info.call.storage_address, *storage_key)) + .collect(); + + // Messages. + let l2_to_l1_payload_lengths = call_info + .execution + .l2_to_l1_messages + .iter() + .map(|message| message.message.payload.0.len()) + .collect(); + + let event_summary = specific_event_summary(call_info); + + let inner_call_execution_resources = call_info.inner_calls.iter().fold( + cairo_vm::vm::runners::cairo_runner::ExecutionResources::default(), + |acc, call_info| &acc + &call_info.resources, + ); + let non_recursive_vm_resources = &call_info.resources - &inner_call_execution_resources; + + blockifier::execution::call_info::ExecutionSummary { + charged_resources: blockifier::execution::call_info::ChargedResources { + vm_resources: non_recursive_vm_resources, + gas_consumed: starknet_api::execution_resources::GasAmount( + call_info.execution.gas_consumed, + ), + }, + executed_class_hashes, + visited_storage_entries, + l2_to_l1_payload_lengths, + event_summary, + } +} + +// Copy of `CallInfo::specific_event_summary()` because that is private +fn specific_event_summary( + call_info: &blockifier::execution::call_info::CallInfo, +) -> blockifier::execution::call_info::EventSummary { + let mut event_summary = blockifier::execution::call_info::EventSummary { + n_events: call_info.execution.events.len(), + ..Default::default() + }; + for blockifier::execution::call_info::OrderedEvent { event, .. } in + call_info.execution.events.iter() + { + let data_len: u64 = event + .data + .0 + .len() + .try_into() + .expect("Conversion from usize to u64 should not fail."); + event_summary.total_event_data_size += data_len; + let key_len: u64 = event + .keys + .len() + .try_into() + .expect("Conversion from usize to u64 should not fail."); + event_summary.total_event_keys += key_len; + } + event_summary +} + impl FunctionInvocation { pub fn from_call_info( call_info: blockifier::execution::call_info::CallInfo, versioned_constants: &blockifier::versioned_constants::VersionedConstants, + gas_vector_computation_mode: &starknet_api::transaction::fields::GasVectorComputationMode, ) -> Self { + let execution_summary = summarize_call_info(&call_info); + + // Message costs + let message_resources = blockifier::fee::resources::MessageResources::new( + execution_summary.l2_to_l1_payload_lengths, + None, + ); + let message_gas_cost = message_resources.to_gas_vector(); + + // Event costs + let archival_gas_costs = &versioned_constants.deprecated_l2_resource_gas_costs; + let event_gas_cost = GasVector::from_l1_gas( + (archival_gas_costs.gas_per_data_felt + * (archival_gas_costs.event_key_factor + * execution_summary.event_summary.total_event_keys + + execution_summary.event_summary.total_event_data_size)) + .to_integer() + .into(), + ); + + // Computation costs + let computation_resources = blockifier::fee::resources::ComputationResources { + vm_resources: execution_summary + .charged_resources + .vm_resources + .filter_unused_builtins(), + n_reverted_steps: 0, + sierra_gas: execution_summary.charged_resources.gas_consumed, + reverted_sierra_gas: 0u64.into(), + }; + let computation_gas_cost = + computation_resources.to_gas_vector(versioned_constants, gas_vector_computation_mode); + + let gas_vector = computation_gas_cost + .checked_add(event_gas_cost) + .unwrap_or_else(|| panic!("resource overflow while adding event costs")) + .checked_add(message_gas_cost) + .unwrap_or_else(|| panic!("resource overflow while adding message costs")); + let messages = ordered_l2_to_l1_messages(&call_info); let internal_calls = call_info .inner_calls .into_iter() - .map(|call_info| Self::from_call_info(call_info, versioned_constants)) + .map(|call_info| { + Self::from_call_info(call_info, versioned_constants, gas_vector_computation_mode) + }) .collect(); let events = call_info @@ -341,22 +458,6 @@ impl FunctionInvocation { .map(IntoFelt::into_felt) .collect(); - let gas_vector = match call_info.tracked_resource { - blockifier::execution::contract_class::TrackedResource::CairoSteps => { - get_vm_resources_cost( - versioned_constants, - &call_info.resources, - 0, - &starknet_api::transaction::fields::GasVectorComputationMode::NoL2Gas, - ) - } - blockifier::execution::contract_class::TrackedResource::SierraGas => GasVector { - l1_gas: 0u64.into(), - l1_data_gas: 0u64.into(), - l2_gas: call_info.execution.gas_consumed.into(), - }, - }; - Self { calldata: call_info .call diff --git a/crates/rpc/src/method/simulate_transactions.rs b/crates/rpc/src/method/simulate_transactions.rs index 583e4a75c1..189884b602 100644 --- a/crates/rpc/src/method/simulate_transactions.rs +++ b/crates/rpc/src/method/simulate_transactions.rs @@ -1322,7 +1322,7 @@ pub(crate) mod tests { pedersen_builtin_applications: 7, ..Default::default() }, - execution_resources: pathfinder_executor::types::InnerCallExecutionResources { l1_gas: 4, l2_gas: 0 }, + execution_resources: pathfinder_executor::types::InnerCallExecutionResources { l1_gas: 5, l2_gas: 0 }, is_reverted: false, } ], @@ -1350,7 +1350,7 @@ pub(crate) mod tests { ], computation_resources: universal_deployer_execute_computation_resources(), execution_resources: pathfinder_executor::types::InnerCallExecutionResources { - l1_gas: 6, + l1_gas: 2, l2_gas: 0, }, is_reverted: false, @@ -1699,7 +1699,7 @@ pub(crate) mod tests { result: vec![test_storage_value.0], computation_resources: invoke_execute_computation_resources(), execution_resources: pathfinder_executor::types::InnerCallExecutionResources { - l1_gas: 3, + l1_gas: 2, l2_gas: 0, }, is_reverted: false,