From de1aecd1284e40a116073fa1f36e8da953060491 Mon Sep 17 00:00:00 2001 From: Avi Cohen Date: Tue, 6 Feb 2024 20:23:24 +0200 Subject: [PATCH] feat(fee): add gas cost for code bytes --- crates/blockifier/src/fee/actual_cost.rs | 1 + crates/blockifier/src/fee/gas_usage.rs | 27 ++++++++++++++++++- crates/blockifier/src/fee/gas_usage_test.rs | 6 +++++ .../src/transaction/transactions.rs | 2 +- .../src/transaction/transactions_test.rs | 11 +++++--- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/crates/blockifier/src/fee/actual_cost.rs b/crates/blockifier/src/fee/actual_cost.rs index 493deb2319..02615e0792 100644 --- a/crates/blockifier/src/fee/actual_cost.rs +++ b/crates/blockifier/src/fee/actual_cost.rs @@ -163,6 +163,7 @@ impl<'a> ActualCostBuilder<'a> { self.calldata_length, self.signature_length, self.l1_payload_size, + self.class_info, use_kzg_da, )?; diff --git a/crates/blockifier/src/fee/gas_usage.rs b/crates/blockifier/src/fee/gas_usage.rs index 8f8a4e0fac..c8c16a03db 100644 --- a/crates/blockifier/src/fee/gas_usage.rs +++ b/crates/blockifier/src/fee/gas_usage.rs @@ -11,6 +11,7 @@ use crate::transaction::objects::{ GasVector, HasRelatedFeeType, ResourcesMapping, TransactionExecutionResult, TransactionPreValidationResult, }; +use crate::transaction::transactions::ClassInfo; use crate::utils::{u128_from_usize, usize_from_u128}; use crate::versioned_constants::VersionedConstants; @@ -22,6 +23,7 @@ pub mod test; /// the Verifier) following the addition of a transaction with the given parameters to a batch; /// e.g., a message from L2 to L1 is followed by a storage write operation in Starknet L1 contract /// which requires gas. +#[allow(clippy::too_many_arguments)] pub fn calculate_tx_gas_usage_vector<'a>( versioned_constants: &VersionedConstants, call_infos: impl Iterator, @@ -29,6 +31,7 @@ pub fn calculate_tx_gas_usage_vector<'a>( calldata_length: usize, signature_length: usize, l1_handler_payload_size: Option, + class_info: Option, use_kzg_da: bool, ) -> TransactionExecutionResult { Ok(calculate_messages_gas_vector(call_infos, l1_handler_payload_size)? @@ -37,7 +40,8 @@ pub fn calculate_tx_gas_usage_vector<'a>( calldata_length, signature_length, versioned_constants, - )) + ) + + get_code_gas_cost(class_info, versioned_constants)) } /// Returns an estimation of the gas usage for processing L1<>L2 messages on L1. Accounts for both @@ -98,6 +102,27 @@ pub fn get_calldata_and_signature_gas_cost( GasVector { l1_gas: l1_milligas / 1000, l1_data_gas: 0 } } +// Returns the gas cost of class information added to L2 via a Declare transaction. Each code felt +// costs a fixed and configurable amount of gas. The cost is 0 for non-Declare transactions. +pub fn get_code_gas_cost( + class_info: Option, + versioned_constants: &VersionedConstants, +) -> GasVector { + if let Some(class_info) = class_info { + let total_code_size = u128_from_usize( + (class_info.bytecode_length() + class_info.sierra_program_length) + * eth_gas_constants::WORD_WIDTH + + class_info.abi_length, + ) + .expect("Failed to convert total code size from usize to u128."); + let l1_milligas = + total_code_size * versioned_constants.l2_resource_gas_costs.milligas_per_code_byte; + GasVector { l1_gas: l1_milligas / 1000, l1_data_gas: 0 } + } else { + GasVector { l1_gas: 0, l1_data_gas: 0 } + } +} + /// Returns the number of felts added to the output data availability segment as a result of adding /// a transaction to a batch. Note that constant cells - such as the one that holds the number of /// modified contracts - are not counted. diff --git a/crates/blockifier/src/fee/gas_usage_test.rs b/crates/blockifier/src/fee/gas_usage_test.rs index f81d6657cc..64efd1bfd0 100644 --- a/crates/blockifier/src/fee/gas_usage_test.rs +++ b/crates/blockifier/src/fee/gas_usage_test.rs @@ -82,6 +82,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) { 0, 0, None, + None, use_kzg_da, ) .unwrap(); @@ -114,6 +115,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) { calldata_length, signature_length, None, + None, use_kzg_da, ) .unwrap(); @@ -129,6 +131,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) { l1_handler_payload_size, signature_length, Some(l1_handler_payload_size), + None, use_kzg_da, ) .unwrap(); @@ -198,6 +201,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) { 0, 0, None, + None, use_kzg_da, ) .unwrap(); @@ -239,6 +243,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) { 0, 0, None, + None, use_kzg_da, ) .unwrap(); @@ -263,6 +268,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) { l1_handler_payload_size, signature_length, Some(l1_handler_payload_size), + None, use_kzg_da, ) .unwrap(); diff --git a/crates/blockifier/src/transaction/transactions.rs b/crates/blockifier/src/transaction/transactions.rs index 62b36deac1..23e9cb9c74 100644 --- a/crates/blockifier/src/transaction/transactions.rs +++ b/crates/blockifier/src/transaction/transactions.rs @@ -111,7 +111,7 @@ pub struct ClassInfo { } impl ClassInfo { - fn _bytecode_length(&self) -> usize { + pub fn bytecode_length(&self) -> usize { self.contract_class.bytecode_length() } } diff --git a/crates/blockifier/src/transaction/transactions_test.rs b/crates/blockifier/src/transaction/transactions_test.rs index 4a99f2ffe1..5cdd403b4b 100644 --- a/crates/blockifier/src/transaction/transactions_test.rs +++ b/crates/blockifier/src/transaction/transactions_test.rs @@ -36,7 +36,7 @@ use crate::execution::execution_utils::{felt_to_stark_felt, stark_felt_to_felt}; use crate::fee::fee_utils::calculate_tx_fee; use crate::fee::gas_usage::{ calculate_tx_gas_usage_vector, estimate_minimal_gas_vector, - get_calldata_and_signature_gas_cost, get_da_gas_cost, + get_calldata_and_signature_gas_cost, get_code_gas_cost, get_da_gas_cost, }; use crate::state::cached_state::{CachedState, StateChangesCount}; use crate::state::errors::StateError; @@ -1087,6 +1087,7 @@ fn test_declare_tx( #[values(false, true)] use_kzg_da: bool, ) { let block_context = &BlockContext::create_for_account_testing_with_kzg(use_kzg_da); + let versioned_constants = &block_context.versioned_constants; let empty_contract = FeatureContract::Empty(empty_contract_version); let account = FeatureContract::AccountWithoutValidations(account_cairo_version); let chain_info = &block_context.chain_info; @@ -1137,6 +1138,8 @@ fn test_declare_tx( ); let da_gas = declare_expected_gas_vector(tx_version, use_kzg_da); + let code_gas: GasVector = get_code_gas_cost(Some(class_info.clone()), versioned_constants); + let gas_usage = code_gas + da_gas.clone(); let expected_execution_info = TransactionExecutionInfo { validate_call_info: expected_validate_call_info, @@ -1146,8 +1149,8 @@ fn test_declare_tx( da_gas: da_gas.clone(), revert_error: None, actual_resources: ResourcesMapping(HashMap::from([ - (abi_constants::L1_GAS_USAGE.to_string(), da_gas.l1_gas.try_into().unwrap()), - (abi_constants::BLOB_GAS_USAGE.to_string(), da_gas.l1_data_gas.try_into().unwrap()), + (abi_constants::L1_GAS_USAGE.to_string(), gas_usage.l1_gas.try_into().unwrap()), + (abi_constants::BLOB_GAS_USAGE.to_string(), gas_usage.l1_data_gas.try_into().unwrap()), (HASH_BUILTIN_NAME.to_string(), 16), ( RANGE_CHECK_BUILTIN_NAME.to_string(), @@ -1514,6 +1517,7 @@ fn test_calculate_tx_gas_usage(#[values(false, true)] use_kzg_da: bool) { calldata_length, signature_length, None, + None, use_kzg_da, ) .unwrap(); @@ -1568,6 +1572,7 @@ fn test_calculate_tx_gas_usage(#[values(false, true)] use_kzg_da: bool) { calldata_length, signature_length, None, + None, use_kzg_da, ) .unwrap();