Skip to content

Commit

Permalink
refactor(blockifier,starknet_api): add GasAmount (u128) type and use …
Browse files Browse the repository at this point in the history
…in blockifier's GasVector
  • Loading branch information
dorimedini-starkware committed Oct 6, 2024
1 parent 54765ac commit 594c451
Show file tree
Hide file tree
Showing 22 changed files with 320 additions and 214 deletions.
5 changes: 3 additions & 2 deletions crates/blockifier/src/blockifier/transaction_executor_test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use assert_matches::assert_matches;
use pretty_assertions::assert_eq;
use rstest::rstest;
use starknet_api::execution_resources::GasAmount;
use starknet_api::test_utils::NonceManager;
use starknet_api::transaction::{Fee, TransactionVersion};
use starknet_api::{declare_tx_args, deploy_account_tx_args, felt, invoke_tx_args, nonce};
Expand Down Expand Up @@ -120,7 +121,7 @@ fn test_declare(
class_hash: declared_contract.get_class_hash(),
compiled_class_hash: declared_contract.get_compiled_class_hash(),
version: tx_version,
resource_bounds: l1_resource_bounds(0, DEFAULT_STRK_L1_GAS_PRICE),
resource_bounds: l1_resource_bounds(GasAmount(0), DEFAULT_STRK_L1_GAS_PRICE),
},
calculate_class_info_for_testing(declared_contract.get_class()),
)
Expand All @@ -140,7 +141,7 @@ fn test_deploy_account(
let tx = deploy_account_tx(
deploy_account_tx_args! {
class_hash: account_contract.get_class_hash(),
resource_bounds: l1_resource_bounds(0, DEFAULT_STRK_L1_GAS_PRICE),
resource_bounds: l1_resource_bounds(GasAmount(0), DEFAULT_STRK_L1_GAS_PRICE),
version,
},
&mut NonceManager::default(),
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier/src/bouncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ pub fn get_tx_weights<S: StateReader>(
state_changes_keys: &StateChangesKeys,
) -> TransactionExecutionResult<BouncerWeights> {
let message_resources = &tx_resources.starknet_resources.messages;
let message_starknet_gas = usize_from_u128(message_resources.get_starknet_gas_cost().l1_gas)
let message_starknet_gas = usize_from_u128(message_resources.get_starknet_gas_cost().l1_gas.0)
.expect("This conversion should not fail as the value is a converted usize.");
let mut additional_os_resources =
get_casm_hash_calculation_resources(state_reader, executed_class_hashes)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier/src/concurrency/versioned_state_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ fn test_run_parallel_txs(max_l1_resource_bounds: ValidResourceBounds) {
let deploy_account_tx_1 = deploy_account_tx(
deploy_account_tx_args! {
class_hash: account_without_validation.get_class_hash(),
resource_bounds: l1_resource_bounds(u64::from(!zero_bounds), DEFAULT_STRK_L1_GAS_PRICE),
resource_bounds: l1_resource_bounds(u128::from(!zero_bounds).into(), DEFAULT_STRK_L1_GAS_PRICE),
},
&mut NonceManager::default(),
);
Expand Down
7 changes: 5 additions & 2 deletions crates/blockifier/src/fee/fee_checks.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use starknet_api::execution_resources::GasAmount;
use starknet_api::transaction::Resource::{self, L1DataGas, L1Gas, L2Gas};
use starknet_api::transaction::{AllResourceBounds, Fee, ResourceBounds, ValidResourceBounds};
use starknet_types_core::felt::Felt;
Expand All @@ -16,7 +17,7 @@ pub enum FeeCheckError {
#[error(
"Insufficient max {resource}: max amount: {max_amount}, actual used: {actual_amount}."
)]
MaxGasAmountExceeded { resource: Resource, max_amount: u128, actual_amount: u128 },
MaxGasAmountExceeded { resource: Resource, max_amount: GasAmount, actual_amount: GasAmount },
#[error("Insufficient max fee: max fee: {}, actual fee: {}.", max_fee.0, actual_fee.0)]
MaxFeeExceeded { max_fee: Fee, actual_fee: Fee },
#[error(
Expand Down Expand Up @@ -75,7 +76,9 @@ impl FeeCheckReport {
match &tx_context.tx_info {
TransactionInfo::Current(info) => get_fee_by_gas_vector(
&tx_context.block_context.block_info,
GasVector::from_l1_gas(info.l1_resource_bounds().max_amount.into()),
GasVector::from_l1_gas(GasAmount(
info.l1_resource_bounds().max_amount.into(),
)),
&FeeType::Strk,
),
TransactionInfo::Deprecated(context) => context.max_fee,
Expand Down
45 changes: 28 additions & 17 deletions crates/blockifier/src/fee/fee_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use assert_matches::assert_matches;
use cairo_vm::types::builtin_name::BuiltinName;
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
use rstest::rstest;
use starknet_api::execution_resources::GasAmount;
use starknet_api::invoke_tx_args;
use starknet_api::transaction::{Fee, GasVectorComputationMode, Resource, ValidResourceBounds};

Expand Down Expand Up @@ -55,10 +56,12 @@ fn test_simple_get_vm_resource_usage(

// Positive flow.
// Verify calculation - in our case, n_steps is the heaviest resource.
let vm_usage_in_l1_gas = (versioned_constants.vm_resource_fee_cost().n_steps
* (u128_from_usize(vm_resource_usage.n_steps + n_reverted_steps)))
.ceil()
.to_integer();
let vm_usage_in_l1_gas = GasAmount(
(versioned_constants.vm_resource_fee_cost().n_steps
* (u128_from_usize(vm_resource_usage.n_steps + n_reverted_steps)))
.ceil()
.to_integer(),
);
let expected_gas_vector = gas_vector_from_vm_usage(
vm_usage_in_l1_gas,
&gas_vector_computation_mode,
Expand All @@ -80,7 +83,8 @@ fn test_simple_get_vm_resource_usage(
vm_resource_usage.builtin_instance_counter.get(&BuiltinName::range_check).unwrap() - 1;
let vm_usage_in_l1_gas = u128_from_usize(
*vm_resource_usage.builtin_instance_counter.get(&BuiltinName::range_check).unwrap(),
);
)
.into();
let expected_gas_vector = gas_vector_from_vm_usage(
vm_usage_in_l1_gas,
&gas_vector_computation_mode,
Expand Down Expand Up @@ -108,10 +112,12 @@ fn test_float_get_vm_resource_usage(
// Positive flow.
// Verify calculation - in our case, n_steps is the heaviest resource.
let n_reverted_steps = 300;
let vm_usage_in_l1_gas = (versioned_constants.vm_resource_fee_cost().n_steps
* u128_from_usize(vm_resource_usage.n_steps + n_reverted_steps))
.ceil()
.to_integer();
let vm_usage_in_l1_gas = GasAmount(
(versioned_constants.vm_resource_fee_cost().n_steps
* u128_from_usize(vm_resource_usage.n_steps + n_reverted_steps))
.ceil()
.to_integer(),
);
let expected_gas_vector = gas_vector_from_vm_usage(
vm_usage_in_l1_gas,
&gas_vector_computation_mode,
Expand All @@ -129,13 +135,14 @@ fn test_float_get_vm_resource_usage(

// Another positive flow, this time the heaviest resource is ecdsa_builtin.
vm_resource_usage.n_steps = 200;
let vm_usage_in_l1_gas =
let vm_usage_in_l1_gas = GasAmount(
((*versioned_constants.vm_resource_fee_cost().builtins.get(&BuiltinName::ecdsa).unwrap())
* u128_from_usize(
*vm_resource_usage.builtin_instance_counter.get(&BuiltinName::ecdsa).unwrap(),
))
.ceil()
.to_integer();
.to_integer(),
);
let expected_gas_vector = gas_vector_from_vm_usage(
vm_usage_in_l1_gas,
&gas_vector_computation_mode,
Expand Down Expand Up @@ -166,9 +173,10 @@ fn test_discounted_gas_overdraft(
#[case] data_gas_price: u128,
#[case] l1_gas_used: usize,
#[case] l1_data_gas_used: usize,
#[case] gas_bound: u64,
#[case] gas_bound: u128,
#[case] expect_failure: bool,
) {
let gas_bound = GasAmount(gas_bound);
let mut block_context = BlockContext::create_for_account_testing();
block_context.block_info.gas_prices = GasPrices::new(
DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(),
Expand Down Expand Up @@ -196,8 +204,8 @@ fn test_discounted_gas_overdraft(
let tx_receipt = TransactionReceipt {
fee: Fee(7),
gas: GasVector {
l1_gas: u128_from_usize(l1_gas_used),
l1_data_gas: u128_from_usize(l1_data_gas_used),
l1_gas: u128_from_usize(l1_gas_used).into(),
l1_data_gas: u128_from_usize(l1_data_gas_used).into(),
..Default::default()
},
..Default::default()
Expand All @@ -213,11 +221,14 @@ fn test_discounted_gas_overdraft(

if expect_failure {
let error = report.error().unwrap();
let expected_actual_amount = u128_from_usize(l1_gas_used)
+ (u128_from_usize(l1_data_gas_used) * data_gas_price) / gas_price;
let expected_actual_amount = (u128_from_usize(l1_gas_used)
+ (u128_from_usize(l1_data_gas_used) * data_gas_price) / gas_price)
.into();
assert_matches!(
error, FeeCheckError::MaxGasAmountExceeded { resource, max_amount, actual_amount }
if max_amount == u128::from(gas_bound) && actual_amount == expected_actual_amount && resource == Resource::L1Gas
if max_amount == gas_bound
&& actual_amount == expected_actual_amount
&& resource == Resource::L1Gas
)
} else {
assert_matches!(report.error(), None);
Expand Down
7 changes: 5 additions & 2 deletions crates/blockifier/src/fee/fee_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use cairo_vm::types::builtin_name::BuiltinName;
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
use num_bigint::BigUint;
use starknet_api::core::ContractAddress;
use starknet_api::execution_resources::GasAmount;
use starknet_api::state::StorageKey;
use starknet_api::transaction::ValidResourceBounds::{AllResources, L1Gas};
use starknet_api::transaction::{AllResourceBounds, Fee, GasVectorComputationMode, Resource};
Expand Down Expand Up @@ -50,7 +51,8 @@ pub fn get_vm_resources_cost(

// Convert Cairo resource usage to L1 gas usage.
// Do so by taking the maximum of the usage of each builtin + step usage.
let vm_l1_gas_usage = vm_resource_fee_costs
let vm_l1_gas_usage = GasAmount(
vm_resource_fee_costs
.builtins
.iter()
// Builtin costs and usage.
Expand All @@ -63,7 +65,8 @@ pub fn get_vm_resources_cost(
vm_resource_usage.total_n_steps() + n_reverted_steps,
)])
.map(|(cost, usage)| (cost * u128_from_usize(usage)).ceil().to_integer())
.fold(0, u128::max);
.fold(0, u128::max),
);

match computation_mode {
GasVectorComputationMode::NoL2Gas => GasVector::from_l1_gas(vm_l1_gas_usage),
Expand Down
20 changes: 12 additions & 8 deletions crates/blockifier/src/fee/gas_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ pub fn get_da_gas_cost(state_changes_count: &StateChangesCount, use_kzg_da: bool

let (l1_gas, blob_gas) = if use_kzg_da {
(
0,
0_u8.into(),
u128_from_usize(
onchain_data_segment_length * eth_gas_constants::DATA_GAS_PER_FIELD_ELEMENT,
),
)
.into(),
)
} else {
// TODO(Yoni, 1/5/2024): count the exact amount of nonzero bytes for each DA entry.
Expand All @@ -70,7 +71,7 @@ pub fn get_da_gas_cost(state_changes_count: &StateChangesCount, use_kzg_da: bool
naive_cost - discount
};

(u128_from_usize(gas), 0)
(u128_from_usize(gas).into(), 0_u8.into())
};

GasVector { l1_gas, l1_data_gas: blob_gas, ..Default::default() }
Expand Down Expand Up @@ -134,11 +135,14 @@ pub fn get_log_message_to_l1_emissions_cost(l2_to_l1_payload_lengths: &[usize])
}

fn get_event_emission_cost(n_topics: usize, data_length: usize) -> GasVector {
GasVector::from_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,
))
GasVector::from_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,
)
.into(),
)
}

/// Returns an estimated lower bound for the gas required by the given account transaction.
Expand Down
30 changes: 18 additions & 12 deletions crates/blockifier/src/fee/gas_usage_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::num::NonZeroU128;

use pretty_assertions::assert_eq;
use rstest::{fixture, rstest};
use starknet_api::execution_resources::GasAmount;
use starknet_api::invoke_tx_args;
use starknet_api::transaction::{EventContent, EventData, EventKey, Fee, GasVectorComputationMode};
use starknet_types_core::felt::Felt;
Expand Down Expand Up @@ -90,7 +91,8 @@ fn test_get_event_gas_cost(
.collect();
let execution_summary = CallInfo::summarize_many(call_infos.iter());
// 8 keys and 11 data words overall.
let expected_gas = (data_word_cost * (event_key_factor * 8_u128 + 11_u128)).to_integer();
let expected_gas =
GasAmount((data_word_cost * (event_key_factor * 8_u128 + 11_u128)).to_integer());
let expected_gas_vector = match gas_vector_computation_mode {
GasVectorComputationMode::NoL2Gas => GasVector::from_l1_gas(expected_gas),
GasVectorComputationMode::All => GasVector::from_l2_gas(expected_gas),
Expand Down Expand Up @@ -146,7 +148,7 @@ fn test_get_da_gas_cost_basic(#[case] state_changes_count: StateChangesCount) {

let computed_gas_vector = get_da_gas_cost(&state_changes_count, true);
assert_eq!(
GasVector::from_l1_data_gas(u128_from_usize(manual_blob_gas_usage)),
GasVector::from_l1_data_gas(u128_from_usize(manual_blob_gas_usage).into()),
computed_gas_vector
);
}
Expand All @@ -155,7 +157,7 @@ fn test_get_da_gas_cost_basic(#[case] state_changes_count: StateChangesCount) {
fn test_onchain_data_discount() {
let use_kzg_da = false;
// Check that there's no negative cost.
assert_eq!(get_da_gas_cost(&StateChangesCount::default(), use_kzg_da).l1_gas, 0);
assert_eq!(get_da_gas_cost(&StateChangesCount::default(), use_kzg_da).l1_gas, GasAmount(0));

// Check discount: modified_contract_felt and fee balance discount.
let state_changes_count = StateChangesCount {
Expand Down Expand Up @@ -186,7 +188,7 @@ fn test_onchain_data_discount() {

assert_eq!(
get_da_gas_cost(&state_changes_count, use_kzg_da).l1_gas,
expected_cost.try_into().unwrap()
u64::try_from(expected_cost).unwrap().into()
);

// Test 10% discount.
Expand All @@ -195,7 +197,7 @@ fn test_onchain_data_discount() {

let cost_without_discount = (state_changes_count.n_storage_updates * 2) * (512 + 100);
let actual_cost = get_da_gas_cost(&state_changes_count, use_kzg_da).l1_gas;
let cost_ratio = ResourceCost::new(actual_cost, u128_from_usize(cost_without_discount));
let cost_ratio = ResourceCost::new(actual_cost.0, u128_from_usize(cost_without_discount));
assert!(cost_ratio <= ResourceCost::new(9, 10));
assert!(cost_ratio >= ResourceCost::new(88, 100));
}
Expand Down Expand Up @@ -227,21 +229,25 @@ fn test_get_message_segment_length(
fn test_discounted_gas_from_gas_vector_computation() {
let tx_context =
BlockContext::create_for_testing().to_tx_context(&account_invoke_tx(invoke_tx_args! {}));
let gas_usage = GasVector { l1_gas: 100, l1_data_gas: 2, ..Default::default() };
let gas_usage =
GasVector { l1_gas: GasAmount(100), l1_data_gas: GasAmount(2), ..Default::default() };
let actual_result = gas_usage.to_discounted_l1_gas(&tx_context);

let result_div_ceil = gas_usage.l1_gas
+ u128_div_ceil(
gas_usage.l1_data_gas * DEFAULT_ETH_L1_DATA_GAS_PRICE,
gas_usage.l1_data_gas.0 * DEFAULT_ETH_L1_DATA_GAS_PRICE,
NonZeroU128::new(DEFAULT_ETH_L1_GAS_PRICE).unwrap(),
);
let result_div_floor = gas_usage.l1_gas
+ (gas_usage.l1_data_gas * DEFAULT_ETH_L1_DATA_GAS_PRICE) / DEFAULT_ETH_L1_GAS_PRICE;
)
.into();
let result_div_floor = GasAmount(
gas_usage.l1_gas.0
+ (gas_usage.l1_data_gas.0 * DEFAULT_ETH_L1_DATA_GAS_PRICE) / DEFAULT_ETH_L1_GAS_PRICE,
);

assert_eq!(actual_result, result_div_ceil);
assert_eq!(actual_result, result_div_floor + 1);
assert_eq!(actual_result, result_div_floor + GasAmount(1));
assert!(
get_fee_by_gas_vector(&tx_context.block_context.block_info, gas_usage, &FeeType::Eth)
<= Fee(actual_result * DEFAULT_ETH_L1_GAS_PRICE)
<= Fee(actual_result.0 * DEFAULT_ETH_L1_GAS_PRICE)
);
}
Loading

0 comments on commit 594c451

Please sign in to comment.