Skip to content

Commit

Permalink
feat(executor): use L2 gas properly during execution
Browse files Browse the repository at this point in the history
In addition, make sure _not_ to use recursive VM resources for inner calls.
  • Loading branch information
kkovaacs committed Jan 23, 2025
1 parent bcb6bc7 commit c44c8d1
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 33 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
39 changes: 29 additions & 10 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,7 @@ pub fn simulate(
tx_info,
state_diff,
block_context.versioned_constants(),
&gas_vector_computation_mode,
),
});
}
Expand Down Expand Up @@ -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| {
Expand Down Expand Up @@ -216,6 +221,7 @@ pub fn trace(
tx_info,
state_diff,
block_context.versioned_constants(),
&gas_vector_computation_mode,
);
traces.push((hash, trace));
}
Expand Down Expand Up @@ -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()
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,
}
}
137 changes: 119 additions & 18 deletions crates/executor/src/types.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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<starknet_api::core::ClassHash> =
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
Expand All @@ -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
Expand Down
6 changes: 3 additions & 3 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: 2,
l2_gas: 0,
},
is_reverted: false,
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit c44c8d1

Please sign in to comment.