From 903641a184aecd76ef5547ae76579f7d0157bf95 Mon Sep 17 00:00:00 2001 From: Dori Medini Date: Mon, 10 Feb 2025 10:27:17 +0200 Subject: [PATCH] feat(blockifier): add ExecutionSummary::to_gas_vector() Signed-off-by: Dori Medini --- crates/blockifier/Cargo.toml | 1 + crates/blockifier/src/execution/call_info.rs | 60 +++++++++++++++- crates/blockifier/src/fee/resources.rs | 74 ++++++++++---------- 3 files changed, 97 insertions(+), 38 deletions(-) diff --git a/crates/blockifier/Cargo.toml b/crates/blockifier/Cargo.toml index 067fb2c5e88..14d0ae8dd3c 100644 --- a/crates/blockifier/Cargo.toml +++ b/crates/blockifier/Cargo.toml @@ -13,6 +13,7 @@ workspace = true cairo_native = ["dep:cairo-native", "starknet_sierra_multicompile/cairo_native"] jemalloc = ["dep:tikv-jemallocator"] native_blockifier = [] +node_api = [] reexecution = ["transaction_serde"] testing = ["rand", "rstest", "rstest_reuse", "starknet_api/testing"] transaction_serde = [] diff --git a/crates/blockifier/src/execution/call_info.rs b/crates/blockifier/src/execution/call_info.rs index 69d5ef17abb..7120b9cbd76 100644 --- a/crates/blockifier/src/execution/call_info.rs +++ b/crates/blockifier/src/execution/call_info.rs @@ -5,8 +5,9 @@ use std::ops::{Add, AddAssign}; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use serde::Serialize; use starknet_api::core::{ClassHash, ContractAddress, EthAddress}; -use starknet_api::execution_resources::GasAmount; +use starknet_api::execution_resources::{GasAmount, GasVector}; use starknet_api::state::StorageKey; +use starknet_api::transaction::fields::GasVectorComputationMode; use starknet_api::transaction::{EventContent, L2ToL1Payload}; use starknet_types_core::felt::Felt; @@ -71,6 +72,25 @@ pub struct EventSummary { pub total_event_data_size: u64, } +impl EventSummary { + pub fn to_gas_vector( + &self, + versioned_constants: &VersionedConstants, + mode: &GasVectorComputationMode, + ) -> GasVector { + let archival_gas_costs = versioned_constants.get_archival_data_gas_costs(mode); + let gas_amount: GasAmount = (archival_gas_costs.gas_per_data_felt + * (archival_gas_costs.event_key_factor * self.total_event_keys + + self.total_event_data_size)) + .to_integer() + .into(); + match mode { + GasVectorComputationMode::All => GasVector::from_l2_gas(gas_amount), + GasVectorComputationMode::NoL2Gas => GasVector::from_l1_gas(gas_amount), + } + } +} + #[derive(Clone, Debug, Default, PartialEq)] pub struct ExecutionSummary { pub charged_resources: ChargedResources, @@ -99,6 +119,44 @@ impl Sum for ExecutionSummary { } } +impl ExecutionSummary { + /// Returns the a gas cost _estimation_ for the execution summary. + /// + /// In particular, this calculation ignores state changes, cost of declared classes, L1 handler + /// payload length, plus Starknet OS overhead. These costs are only accounted for on a + /// transaction level and cannot be computed based on a single execution summary. + #[cfg(feature = "node_api")] + pub fn to_partial_gas_vector( + self, + versioned_constants: &VersionedConstants, + mode: &GasVectorComputationMode, + ) -> GasVector { + use crate::fee::resources::{ComputationResources, MessageResources}; + + let computation_resources = ComputationResources { + vm_resources: self.charged_resources.vm_resources, + n_reverted_steps: 0, + sierra_gas: self.charged_resources.gas_consumed, + reverted_sierra_gas: 0u64.into(), + }; + + [ + computation_resources.to_gas_vector(versioned_constants, mode), + self.event_summary.to_gas_vector(versioned_constants, mode), + MessageResources::new(self.l2_to_l1_payload_lengths, None).to_gas_vector(), + ] + .iter() + .fold(GasVector::ZERO, |accumulator, cost| { + accumulator.checked_add(*cost).unwrap_or_else(|| { + panic!( + "Execution summary to gas vector overflowed: tried to add {cost:?} to \ + {accumulator:?}" + ); + }) + }) + } +} + /// L2 resources counted for fee charge. /// When all execution will be using gas (no VM mode), this should be removed, and the gas_consumed /// field should be used for fee collection. diff --git a/crates/blockifier/src/fee/resources.rs b/crates/blockifier/src/fee/resources.rs index 6c0ec1d75a9..ae2083fc0a6 100644 --- a/crates/blockifier/src/fee/resources.rs +++ b/crates/blockifier/src/fee/resources.rs @@ -18,7 +18,7 @@ use crate::fee::gas_usage::{ use crate::state::cached_state::{StateChanges, StateChangesCountForFee}; use crate::transaction::errors::TransactionFeeError; use crate::utils::u64_from_usize; -use crate::versioned_constants::{AllocationCost, ArchivalDataGasCosts, VersionedConstants}; +use crate::versioned_constants::{AllocationCost, VersionedConstants}; pub type TransactionFeeResult = Result; @@ -250,60 +250,60 @@ impl ArchivalDataResources { versioned_constants: &VersionedConstants, mode: &GasVectorComputationMode, ) -> GasVector { - let archival_gas_costs = match mode { - // Computation is in L2 gas units. - GasVectorComputationMode::All => &versioned_constants.archival_data_gas_costs, - // Computation is in L1 gas units. - GasVectorComputationMode::NoL2Gas => { - &versioned_constants.deprecated_l2_resource_gas_costs - } - }; - let gas_amount = [ - self.get_calldata_and_signature_gas_cost(archival_gas_costs), - self.get_code_gas_cost(archival_gas_costs), - self.get_events_gas_cost(archival_gas_costs), + [ + self.get_calldata_and_signature_gas_cost(versioned_constants, mode), + self.get_code_gas_cost(versioned_constants, mode), + self.event_summary.to_gas_vector(versioned_constants, mode), ] .into_iter() - .fold(GasAmount::ZERO, |accumulator, cost| { + .fold(GasVector::ZERO, |accumulator, cost| { accumulator.checked_add(cost).unwrap_or_else(|| { panic!( "Archival data resources to gas vector overflowed: tried to add \ - {accumulator:?} gas to {cost:?} gas.", + {accumulator:?} gas vector to {cost:?} gas vector.", ) }) - }); - match mode { - GasVectorComputationMode::All => GasVector::from_l2_gas(gas_amount), - GasVectorComputationMode::NoL2Gas => GasVector::from_l1_gas(gas_amount), - } + }) } /// Returns the cost for transaction calldata and transaction signature. Each felt costs a /// fixed and configurable amount of gas. This cost represents the cost of storing the - /// calldata and the signature on L2. The result is given in L1/L2 gas units, depending on the - /// mode. + /// calldata and the signature on L2. fn get_calldata_and_signature_gas_cost( &self, - archival_gas_costs: &ArchivalDataGasCosts, - ) -> GasAmount { + versioned_constants: &VersionedConstants, + mode: &GasVectorComputationMode, + ) -> GasVector { + let archival_gas_costs = versioned_constants.get_archival_data_gas_costs(mode); + // TODO(Avi, 20/2/2024): Calculate the number of bytes instead of the number of felts. let total_data_size = u64_from_usize(self.calldata_length + self.signature_length); - (archival_gas_costs.gas_per_data_felt * total_data_size).to_integer().into() - } + let gas_amount = + (archival_gas_costs.gas_per_data_felt * total_data_size).to_integer().into(); - /// Returns the cost of declared class codes in L1/L2 gas units, depending on the mode. - fn get_code_gas_cost(&self, archival_gas_costs: &ArchivalDataGasCosts) -> GasAmount { - (archival_gas_costs.gas_per_code_byte * u64_from_usize(self.code_size)).to_integer().into() + match mode { + GasVectorComputationMode::All => GasVector::from_l2_gas(gas_amount), + GasVectorComputationMode::NoL2Gas => GasVector::from_l1_gas(gas_amount), + } } - /// Returns the cost of the transaction's emmited events in L1/L2 gas units, depending on the - /// mode. - fn get_events_gas_cost(&self, archival_gas_costs: &ArchivalDataGasCosts) -> GasAmount { - (archival_gas_costs.gas_per_data_felt - * (archival_gas_costs.event_key_factor * self.event_summary.total_event_keys - + self.event_summary.total_event_data_size)) - .to_integer() - .into() + /// Returns the cost of declared class codes. + fn get_code_gas_cost( + &self, + versioned_constants: &VersionedConstants, + mode: &GasVectorComputationMode, + ) -> GasVector { + let archival_gas_costs = versioned_constants.get_archival_data_gas_costs(mode); + + let gas_amount: GasAmount = (archival_gas_costs.gas_per_code_byte + * u64_from_usize(self.code_size)) + .to_integer() + .into(); + + match mode { + GasVectorComputationMode::All => GasVector::from_l2_gas(gas_amount), + GasVectorComputationMode::NoL2Gas => GasVector::from_l1_gas(gas_amount), + } } }