Skip to content

Commit

Permalink
Merge pull request #2511 from eqlabs/krisztian/call-level-gas-calcula…
Browse files Browse the repository at this point in the history
…tion

fix(executor): fix L2 gas computation and inner-call gas estimation
  • Loading branch information
kkovaacs authored Jan 30, 2025
2 parents e8ba364 + 222b969 commit 9365aef
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 35 deletions.
5 changes: 3 additions & 2 deletions crates/executor/src/estimate.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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,
Expand Down
49 changes: 38 additions & 11 deletions crates/executor/src/simulate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -131,6 +134,8 @@ pub fn simulate(
tx_info,
state_diff,
block_context.versioned_constants(),
&gas_vector_computation_mode,
block_context.block_info().use_kzg_da,
),
});
}
Expand Down Expand Up @@ -182,10 +187,11 @@ pub fn trace(
let mut traces = Vec::with_capacity(transactions.len());
for (transaction_idx, tx) in transactions.into_iter().enumerate() {
let hash = transaction_hash(&tx);
let _span = tracing::debug_span!("simulate", transaction_hash=%super::transaction::transaction_hash(&tx), %transaction_idx).entered();
let _span = tracing::debug_span!("trace", transaction_hash=%super::transaction::transaction_hash(&tx), %transaction_idx).entered();

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| {
Expand All @@ -209,11 +215,15 @@ pub fn trace(
})?;
tx_state.commit();

tracing::trace!("Transaction tracing finished");

let trace = to_trace(
tx_type,
tx_info,
state_diff,
block_context.versioned_constants(),
&gas_vector_computation_mode,
block_context.block_info().use_kzg_da,
);
traces.push((hash, trace));
}
Expand Down Expand Up @@ -362,16 +372,33 @@ fn to_trace(
execution_info: blockifier::transaction::objects::TransactionExecutionInfo,
state_diff: StateDiff,
versioned_constants: &VersionedConstants,
gas_vector_computation_mode: &GasVectorComputationMode,
use_kzg_da: bool,
) -> 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,
use_kzg_da,
)
});
let maybe_function_invocation = execution_info.execute_call_info.map(|call_info| {
FunctionInvocation::from_call_info(
call_info,
versioned_constants,
gas_vector_computation_mode,
use_kzg_da,
)
});
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,
use_kzg_da,
)
});

let computation_resources = validate_invocation
.as_ref()
Expand Down
39 changes: 39 additions & 0 deletions crates/executor/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
}
}
77 changes: 57 additions & 20 deletions crates/executor/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::{BTreeMap, HashSet};

use blockifier::execution::call_info::OrderedL2ToL1Message;
use blockifier::fee::fee_utils::get_vm_resources_cost;
use blockifier::fee::resources::{StarknetResources, TransactionResources};
use blockifier::transaction::objects::TransactionExecutionInfo;
use pathfinder_common::{
CasmHash,
Expand Down Expand Up @@ -314,16 +314,69 @@ pub struct DataAvailabilityResources {
}

impl FunctionInvocation {
// This estimation purposefully ignores some of the gas costs since we don't
// have all the necessary defails to compute them and those will be taken
// into account only when computing the transaction receipt.
// Ignored costs include state change costs, code size related costs for
// DECLARE, L1 handler payload size and Starknet OS overhead.
fn estimate_gas_consumed(
call_info: &blockifier::execution::call_info::CallInfo,
versioned_constants: &blockifier::versioned_constants::VersionedConstants,
gas_vector_computation_mode: &starknet_api::transaction::fields::GasVectorComputationMode,
use_kzg_da: bool,
) -> GasVector {
let execution_summary = call_info.summarize(versioned_constants);
let sierra_gas = execution_summary.charged_resources.gas_consumed;
let vm_resources = execution_summary
.charged_resources
.vm_resources
.filter_unused_builtins();
let state_changes = blockifier::state::cached_state::StateChanges::default();
let state_resources = blockifier::fee::resources::StateResources::new(
&state_changes,
None,
Default::default(),
);
let starknet_resources =
StarknetResources::new(0, 0, 0, state_resources, None, execution_summary);
let tx_resources = TransactionResources {
starknet_resources,
computation: blockifier::fee::resources::ComputationResources {
vm_resources,
n_reverted_steps: 0,
sierra_gas,
reverted_sierra_gas: 0u64.into(),
},
};
tx_resources.to_gas_vector(versioned_constants, use_kzg_da, gas_vector_computation_mode)
}

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,
use_kzg_da: bool,
) -> Self {
let gas_consumed = Self::estimate_gas_consumed(
&call_info,
versioned_constants,
gas_vector_computation_mode,
use_kzg_da,
);

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,
use_kzg_da,
)
})
.collect();

let events = call_info
Expand All @@ -341,22 +394,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
Expand All @@ -382,8 +419,8 @@ impl FunctionInvocation {
result,
computation_resources: call_info.resources.into(),
execution_resources: InnerCallExecutionResources {
l1_gas: gas_vector.l1_gas.0.into(),
l2_gas: gas_vector.l2_gas.0.into(),
l1_gas: gas_consumed.l1_gas.0.into(),
l2_gas: gas_consumed.l2_gas.0.into(),
},
is_reverted: call_info.execution.failed,
}
Expand Down
4 changes: 2 additions & 2 deletions crates/rpc/src/method/simulate_transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
],
Expand Down Expand Up @@ -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: 7,
l2_gas: 0,
},
is_reverted: false,
Expand Down

0 comments on commit 9365aef

Please sign in to comment.