Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

chore(fee): integer VM gas usage #1410

Merged
merged 2 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/blockifier/src/fee/fee_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::test_utils::contracts::FeatureContract;
use crate::test_utils::initial_test_state::test_state;
use crate::test_utils::{CairoVersion, BALANCE};
use crate::transaction::errors::TransactionFeeError;
use crate::transaction::objects::ResourcesMapping;
use crate::transaction::objects::{GasVector, ResourcesMapping};
use crate::transaction::test_utils::{account_invoke_tx, l1_resource_bounds};
use crate::versioned_constants::VersionedConstants;

Expand All @@ -42,7 +42,7 @@ fn test_calculate_l1_gas_by_vm_usage() {
// Verify calculation - in our case, n_steps is the heaviest resource.
let l1_gas_by_vm_usage = vm_resource_usage.0.get(constants::N_STEPS_RESOURCE).unwrap();
assert_eq!(
*l1_gas_by_vm_usage as f64,
GasVector { l1_gas: *l1_gas_by_vm_usage as u128, blob_gas: 0 },
calculate_l1_gas_by_vm_usage(&versioned_constants, &vm_resource_usage).unwrap()
);

Expand Down
13 changes: 7 additions & 6 deletions crates/blockifier/src/fee/fee_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn extract_l1_blob_gas_usage(resources: &ResourcesMapping) -> (usize, Resour
pub fn calculate_l1_gas_by_vm_usage(
versioned_constants: &VersionedConstants,
vm_resource_usage: &ResourcesMapping,
) -> TransactionFeeResult<f64> {
) -> TransactionFeeResult<GasVector> {
let vm_resource_fee_costs = &versioned_constants.vm_resource_fee_cost;
let vm_resource_names = HashSet::<&String>::from_iter(vm_resource_usage.0.keys());
if !vm_resource_names.is_subset(&HashSet::from_iter(vm_resource_fee_costs.keys())) {
Expand All @@ -57,7 +57,8 @@ pub fn calculate_l1_gas_by_vm_usage(
})
.fold(f64::NAN, f64::max);

Ok(vm_l1_gas_usage)
// TODO(Dori, 1/5/2024): Check this conversion.
Ok(GasVector { l1_gas: vm_l1_gas_usage.ceil() as u128, blob_gas: 0 })
}

/// Computes and returns the total L1 gas consumption.
Expand All @@ -69,14 +70,14 @@ pub fn calculate_tx_gas_vector(
) -> TransactionFeeResult<GasVector> {
let (l1_gas_usage, vm_resources) = extract_l1_gas_and_vm_usage(resources);
let (l1_blob_gas_usage, vm_resources) = extract_l1_blob_gas_usage(&vm_resources);
let l1_gas_by_vm_usage = calculate_l1_gas_by_vm_usage(versioned_constants, &vm_resources)?;
let total_l1_gas_usage = l1_gas_usage as f64 + l1_gas_by_vm_usage;
let vm_usage_gas_vector = calculate_l1_gas_by_vm_usage(versioned_constants, &vm_resources)?;

Ok(GasVector {
l1_gas: total_l1_gas_usage.ceil() as u128,
l1_gas: u128_from_usize(l1_gas_usage)
.expect("Conversion from usize to u128 should not fail."),
blob_gas: u128_from_usize(l1_blob_gas_usage)
.expect("Conversion from usize to u128 should not fail."),
})
} + vm_usage_gas_vector)
}

pub fn get_fee_by_gas_vector(
Expand Down
64 changes: 40 additions & 24 deletions crates/blockifier/src/fee/gas_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,32 @@ pub fn calculate_messages_gas_vector<'a>(
let n_l2_to_l1_messages = l2_to_l1_payload_lengths.len();
let n_l1_to_l2_messages = usize::from(l1_handler_payload_size.is_some());

let starknet_gas_usage =
// Starknet's updateState gets the message segment as an argument.
message_segment_length * eth_gas_constants::GAS_PER_MEMORY_WORD
// Starknet's updateState increases a (storage) counter for each L2-to-L1 message.
+ n_l2_to_l1_messages * eth_gas_constants::GAS_PER_ZERO_TO_NONZERO_STORAGE_SET
// Starknet's updateState decreases a (storage) counter for each L1-to-L2 consumed message.
// (Note that we will probably get a refund of 15,000 gas for each consumed message but we
// ignore it since refunded gas cannot be used for the current transaction execution).
+ n_l1_to_l2_messages * eth_gas_constants::GAS_PER_COUNTER_DECREASE
+ get_consumed_message_to_l2_emissions_cost(l1_handler_payload_size)
+ get_log_message_to_l1_emissions_cost(&l2_to_l1_payload_lengths);

let sharp_gas_usage = message_segment_length * eth_gas_constants::SHARP_GAS_PER_MEMORY_WORD;
let starknet_gas_usage = GasVector {
// Starknet's updateState gets the message segment as an argument.
l1_gas: u128_from_usize(
message_segment_length * eth_gas_constants::GAS_PER_MEMORY_WORD
// Starknet's updateState increases a (storage) counter for each L2-to-L1 message.
+ n_l2_to_l1_messages * eth_gas_constants::GAS_PER_ZERO_TO_NONZERO_STORAGE_SET
// Starknet's updateState decreases a (storage) counter for each L1-to-L2 consumed
// message (note that we will probably get a refund of 15,000 gas for each consumed
// message but we ignore it since refunded gas cannot be used for the current
// transaction execution).
+ n_l1_to_l2_messages * eth_gas_constants::GAS_PER_COUNTER_DECREASE,
)
.expect("Could not convert starknet gas usage from usize to u128."),
blob_gas: 0,
} + get_consumed_message_to_l2_emissions_cost(l1_handler_payload_size)
+ get_log_message_to_l1_emissions_cost(&l2_to_l1_payload_lengths);

Ok(GasVector {
l1_gas: u128_from_usize(starknet_gas_usage + sharp_gas_usage)
.expect("Failed to convert messages L1 gas usage from usize to u128."),
let sharp_gas_usage = GasVector {
l1_gas: u128_from_usize(
message_segment_length * eth_gas_constants::SHARP_GAS_PER_MEMORY_WORD,
)
.expect("Could not convert sharp gas usage from usize to u128."),
blob_gas: 0,
})
};

Ok(starknet_gas_usage + sharp_gas_usage)
}

/// Returns the number of felts added to the output data availability segment as a result of adding
Expand Down Expand Up @@ -155,9 +162,12 @@ pub fn get_message_segment_length(

/// Returns the cost of ConsumedMessageToL2 event emissions caused by an L1 handler with the given
/// payload size.
pub fn get_consumed_message_to_l2_emissions_cost(l1_handler_payload_size: Option<usize>) -> usize {
pub fn get_consumed_message_to_l2_emissions_cost(
l1_handler_payload_size: Option<usize>,
) -> GasVector {
match l1_handler_payload_size {
None => 0, // The corresponding transaction is not an L1 handler.,
// The corresponding transaction is not an L1 handler.,
None => GasVector { l1_gas: 0, blob_gas: 0 },
Some(l1_handler_payload_size) => {
get_event_emission_cost(
constants::CONSUMED_MSG_TO_L2_N_TOPICS,
Expand All @@ -169,7 +179,7 @@ pub fn get_consumed_message_to_l2_emissions_cost(l1_handler_payload_size: Option
}

/// Returns the cost of LogMessageToL1 event emissions caused by the given messages payload length.
pub fn get_log_message_to_l1_emissions_cost(l2_to_l1_payload_lengths: &[usize]) -> usize {
pub fn get_log_message_to_l1_emissions_cost(l2_to_l1_payload_lengths: &[usize]) -> GasVector {
l2_to_l1_payload_lengths
.iter()
.map(|length| {
Expand All @@ -182,10 +192,16 @@ pub fn get_log_message_to_l1_emissions_cost(l2_to_l1_payload_lengths: &[usize])
.sum()
}

fn get_event_emission_cost(n_topics: usize, data_length: usize) -> usize {
eth_gas_constants::GAS_PER_LOG
+ (n_topics + constants::N_DEFAULT_TOPICS) * eth_gas_constants::GAS_PER_LOG_TOPIC
+ data_length * eth_gas_constants::GAS_PER_LOG_DATA_WORD
fn get_event_emission_cost(n_topics: usize, data_length: usize) -> GasVector {
GasVector {
l1_gas: u128_from_usize(
eth_gas_constants::GAS_PER_LOG
+ (n_topics + constants::N_DEFAULT_TOPICS) * eth_gas_constants::GAS_PER_LOG_TOPIC
+ data_length * eth_gas_constants::GAS_PER_LOG_DATA_WORD,
)
.expect("Cannot convert event emission gas from usize to u128."),
blob_gas: 0,
}
}

/// Return an estimated lower bound for the L1 gas on an account transaction.
Expand Down
8 changes: 6 additions & 2 deletions crates/blockifier/src/fee/gas_usage_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
let message_segment_length = get_message_segment_length(&[], Some(l1_handler_payload_size));
let manual_starknet_gas_usage = message_segment_length * eth_gas_constants::GAS_PER_MEMORY_WORD
+ eth_gas_constants::GAS_PER_COUNTER_DECREASE
+ get_consumed_message_to_l2_emissions_cost(Some(l1_handler_payload_size));
+ usize_from_u128(
get_consumed_message_to_l2_emissions_cost(Some(l1_handler_payload_size)).l1_gas,
)
.unwrap();
let manual_sharp_gas_usage =
message_segment_length * eth_gas_constants::SHARP_GAS_PER_MEMORY_WORD;
let manual_gas_computation = GasVector {
Expand Down Expand Up @@ -180,7 +183,8 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
let n_l2_to_l1_messages = l2_to_l1_payload_lengths.len();
let manual_starknet_gas_usage = message_segment_length * eth_gas_constants::GAS_PER_MEMORY_WORD
+ n_l2_to_l1_messages * eth_gas_constants::GAS_PER_ZERO_TO_NONZERO_STORAGE_SET
+ get_log_message_to_l1_emissions_cost(&l2_to_l1_payload_lengths);
+ usize_from_u128(get_log_message_to_l1_emissions_cost(&l2_to_l1_payload_lengths).l1_gas)
.unwrap();
let manual_sharp_gas_usage = message_segment_length
* eth_gas_constants::SHARP_GAS_PER_MEMORY_WORD
+ usize_from_u128(get_da_gas_cost(l2_to_l1_state_changes_count, use_kzg_da).l1_gas)
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier/src/transaction/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ pub struct DeprecatedAccountTransactionContext {
pub max_fee: Fee,
}

#[derive(derive_more::Add, Clone, Debug, Default, Eq, PartialEq)]
#[derive(derive_more::Add, derive_more::Sum, Clone, Debug, Default, Eq, PartialEq)]
pub struct GasVector {
pub l1_gas: u128,
pub blob_gas: u128,
Expand Down
Loading