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

Commit

Permalink
feat(fee): charge for signatures per byte
Browse files Browse the repository at this point in the history
  • Loading branch information
avi-starkware committed Feb 11, 2024
1 parent ef063e3 commit e8b8e87
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 20 deletions.
6 changes: 5 additions & 1 deletion crates/blockifier/resources/versioned_constants.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
"max_calldata_length": 4000,
"max_contract_bytecode_size": 61440
},
"milli_gas_per_calldata_byte": 40,
"l2_resource_gas_costs": {
"milligas_per_data_word": 1280,
"event_key_factor": 2,
"milligas_per_code_word": 28000
},
"invoke_tx_max_n_steps": 3000000,
"max_recursion_depth": 50,
"os_constants": {
Expand Down
3 changes: 1 addition & 2 deletions crates/blockifier/src/fee/actual_cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ pub struct ActualCostBuilder<'a> {
l1_payload_size: Option<usize>,
calldata_length: usize,
n_reverted_steps: usize,
// TODO(Avi,10/02/2024): use this field and remove the clippy tag.
#[allow(dead_code)]
signature_length: usize,
class_info: Option<ClassInfo>,
}
Expand Down Expand Up @@ -163,6 +161,7 @@ impl<'a> ActualCostBuilder<'a> {
non_optional_call_infos,
state_changes_count,
self.calldata_length,
self.signature_length,
self.l1_payload_size,
use_kzg_da,
)?;
Expand Down
22 changes: 15 additions & 7 deletions crates/blockifier/src/fee/gas_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,17 @@ pub fn calculate_tx_gas_usage_vector<'a>(
call_infos: impl Iterator<Item = &'a CallInfo>,
state_changes_count: StateChangesCount,
calldata_length: usize,
signature_length: usize,
l1_handler_payload_size: Option<usize>,
use_kzg_da: bool,
) -> TransactionExecutionResult<GasVector> {
Ok(calculate_messages_gas_vector(call_infos, l1_handler_payload_size)?
+ get_da_gas_cost(state_changes_count, use_kzg_da)
+ get_calldata_gas_cost(calldata_length, versioned_constants))
+ get_calldata_and_signature_gas_cost(
calldata_length,
signature_length,
versioned_constants,
))
}

/// Returns an estimation of the gas usage for processing L1<>L2 messages on L1. Accounts for both
Expand Down Expand Up @@ -75,17 +80,20 @@ pub fn calculate_messages_gas_vector<'a>(
Ok(starknet_gas_usage + sharp_gas_usage)
}

// Return the gas cost for transaction calldata. Each calldata felt costs a fixed and configurable
// amount of gas. This cost represents the cost of storing the calldata on L2.
pub fn get_calldata_gas_cost(
// Return the gas 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.
pub fn get_calldata_and_signature_gas_cost(
calldata_length: usize,
signature_length: usize,
versioned_constants: &VersionedConstants,
) -> GasVector {
// TODO(Avi, 28/2/2024): Use rational numbers to calculate the gas cost once implemented.
// TODO(Avi, 20/2/2024): Calculate the number of bytes instead of the number of felts.
let milli_gas_per_calldata_word =
versioned_constants.milli_gas_per_calldata_byte * eth_gas_constants::WORD_WIDTH;
let calldata_gas_cost = calldata_length * milli_gas_per_calldata_word / 1000;
let l2_resource_gas_costs = versioned_constants.get_l2_resource_gas_costs();
let calldata_gas_cost =
(calldata_length + signature_length) * l2_resource_gas_costs.milligas_per_data_word / 1000;

GasVector {
l1_gas: u128_from_usize(calldata_gas_cost)
.expect("Could not convert calldata gas cost from usize to u128."),
Expand Down
22 changes: 19 additions & 3 deletions crates/blockifier/src/fee/gas_usage_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use starknet_api::transaction::L2ToL1Payload;
use crate::execution::call_info::{CallExecution, CallInfo, MessageToL1, OrderedL2ToL1Message};
use crate::fee::eth_gas_constants;
use crate::fee::gas_usage::{
calculate_tx_gas_usage_vector, get_calldata_gas_cost,
calculate_tx_gas_usage_vector, get_calldata_and_signature_gas_cost,
get_consumed_message_to_l2_emissions_cost, get_da_gas_cost,
get_log_message_to_l1_emissions_cost, get_message_segment_length,
};
Expand Down Expand Up @@ -81,6 +81,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
std::iter::empty(),
StateChangesCount::default(),
0,
0,
None,
use_kzg_da,
)
Expand All @@ -99,15 +100,21 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
// Manual calculation.
let manual_starknet_gas_usage = 0;
let calldata_length = 0;
let signature_length = 0;
let manual_gas_vector = GasVector { l1_gas: manual_starknet_gas_usage, ..Default::default() }
+ get_da_gas_cost(deploy_account_state_changes_count, use_kzg_da)
+ get_calldata_gas_cost(calldata_length, &versioned_constants);
+ get_calldata_and_signature_gas_cost(
calldata_length,
signature_length,
&versioned_constants,
);

let deploy_account_gas_usage_vector = calculate_tx_gas_usage_vector(
&versioned_constants,
std::iter::empty(),
deploy_account_state_changes_count,
calldata_length,
signature_length,
None,
use_kzg_da,
)
Expand All @@ -122,6 +129,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
std::iter::empty(),
StateChangesCount::default(),
l1_handler_payload_size,
signature_length,
Some(l1_handler_payload_size),
use_kzg_da,
)
Expand All @@ -136,7 +144,12 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
)
.unwrap()
+ usize_from_u128(
get_calldata_gas_cost(l1_handler_payload_size, &versioned_constants).l1_gas,
get_calldata_and_signature_gas_cost(
l1_handler_payload_size,
signature_length,
&versioned_constants,
)
.l1_gas,
)
.unwrap();
let manual_sharp_gas_usage =
Expand Down Expand Up @@ -190,6 +203,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
call_infos_iter.clone(),
l2_to_l1_state_changes_count,
0,
0,
None,
use_kzg_da,
)
Expand Down Expand Up @@ -230,6 +244,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
std::iter::empty(),
storage_writes_state_changes_count,
0,
0,
None,
use_kzg_da,
)
Expand All @@ -253,6 +268,7 @@ fn test_calculate_tx_gas_usage_basic(#[values(false, true)] use_kzg_da: bool) {
call_infos_iter,
combined_state_changes_count,
l1_handler_payload_size,
signature_length,
Some(l1_handler_payload_size),
use_kzg_da,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ fn test_simulate_validate_charge_fee_fail_validate(
} = create_flavors_test_state(&block_context.chain_info, cairo_version);

// Validation scenario: fallible validation.
let (actual_gas_used, actual_fee) = gas_and_fee(30786, validate, &fee_type);
let (actual_gas_used, actual_fee) = gas_and_fee(30789, validate, &fee_type);
let result = account_invoke_tx(invoke_tx_args! {
max_fee,
resource_bounds: l1_resource_bounds(MAX_L1_GAS_AMOUNT, MAX_L1_GAS_PRICE),
Expand Down
16 changes: 11 additions & 5 deletions crates/blockifier/src/transaction/transactions_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ use crate::execution::errors::EntryPointExecutionError;
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_gas_cost,
get_da_gas_cost,
calculate_tx_gas_usage_vector, estimate_minimal_gas_vector,
get_calldata_and_signature_gas_cost, get_da_gas_cost,
};
use crate::state::cached_state::{CachedState, StateChangesCount};
use crate::state::errors::StateError;
Expand Down Expand Up @@ -353,7 +353,8 @@ fn test_invoke_tx(
// Extract invoke transaction fields for testing, as it is consumed when creating an account
// transaction.
let calldata = Calldata(Arc::clone(&invoke_tx.calldata().0));
let calldata_length = &invoke_tx.calldata().0.len();
let calldata_length = invoke_tx.calldata().0.len();
let signature_length = invoke_tx.signature().0.len();
let sender_address = invoke_tx.sender_address();

let account_tx = AccountTransaction::Invoke(invoke_tx);
Expand Down Expand Up @@ -430,7 +431,8 @@ fn test_invoke_tx(
};

let da_gas = get_da_gas_cost(state_changes_count, use_kzg_da);
let calldata_gas = get_calldata_gas_cost(*calldata_length, versioned_constants);
let calldata_gas =
get_calldata_and_signature_gas_cost(calldata_length, signature_length, versioned_constants);
let expected_execution_info = TransactionExecutionInfo {
validate_call_info: expected_validate_call_info,
execute_call_info: expected_execute_call_info,
Expand All @@ -446,7 +448,7 @@ fn test_invoke_tx(
abi_constants::L1_GAS_USAGE.to_string(),
usize_from_u128(da_gas.l1_gas + calldata_gas.l1_gas).unwrap(),
),
(HASH_BUILTIN_NAME.to_string(), 14 + calldata_length),
(HASH_BUILTIN_NAME.to_string(), 14 + &calldata_length),
(RANGE_CHECK_BUILTIN_NAME.to_string(), expected_arguments.range_check),
(abi_constants::N_STEPS_RESOURCE.to_string(), expected_arguments.n_steps),
])),
Expand Down Expand Up @@ -1492,6 +1494,7 @@ fn test_calculate_tx_gas_usage(#[values(false, true)] use_kzg_da: bool) {
test_contract.get_instance_address(0),
));
let calldata_length = account_tx.calldata_length();
let signature_length = account_tx.signature_length();
let fee_token_address = chain_info.fee_token_address(&account_tx.fee_type());
let tx_execution_info = account_tx.execute(state, block_context, true, true).unwrap();

Expand All @@ -1509,6 +1512,7 @@ fn test_calculate_tx_gas_usage(#[values(false, true)] use_kzg_da: bool) {
std::iter::empty(),
state_changes_count,
calldata_length,
signature_length,
None,
use_kzg_da,
)
Expand Down Expand Up @@ -1544,6 +1548,7 @@ fn test_calculate_tx_gas_usage(#[values(false, true)] use_kzg_da: bool) {
});

let calldata_length = account_tx.calldata_length();
let signature_length = account_tx.signature_length();
let tx_execution_info = account_tx.execute(state, block_context, true, true).unwrap();
// For the balance update of the sender and the recipient.
let n_storage_updates = 2;
Expand All @@ -1561,6 +1566,7 @@ fn test_calculate_tx_gas_usage(#[values(false, true)] use_kzg_da: bool) {
std::iter::empty(),
state_changes_count,
calldata_length,
signature_length,
None,
use_kzg_da,
)
Expand Down
16 changes: 15 additions & 1 deletion crates/blockifier/src/versioned_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,13 @@ pub struct VersionedConstants {
// TODO: Consider making this a struct, this will require change the way we access these
// values.
vm_resource_fee_cost: Arc<HashMap<String, f64>>,
pub milli_gas_per_calldata_byte: usize,

// Cairo OS constants.
// Note: if loaded from a json file, there are some assumptions made on its structure.
// See the struct's docstring for more details.
os_constants: Arc<OSConstants>,

l2_resource_gas_costs: Arc<L2ResourceGasCosts>,
}

impl VersionedConstants {
Expand Down Expand Up @@ -114,6 +115,10 @@ impl VersionedConstants {
self.os_resources.get_additional_os_syscall_resources(syscall_counter)
}

pub fn get_l2_resource_gas_costs(&self) -> &L2ResourceGasCosts {
&self.l2_resource_gas_costs
}

#[cfg(any(feature = "testing", test))]
pub fn create_for_account_testing() -> Self {
let vm_resource_fee_cost = Arc::new(HashMap::from([
Expand All @@ -139,6 +144,15 @@ impl TryFrom<&Path> for VersionedConstants {
}
}

#[derive(Clone, Debug, Default, Deserialize)]
pub struct L2ResourceGasCosts {
// TODO(barak, 18/03/2024): Once we start charging per byte change to milligas_per_data_byte,
// divide the value by 32 in the JSON file.
pub milligas_per_data_word: usize,
pub event_key_factor: usize,
pub milligas_per_code_word: usize,
}

#[derive(Clone, Debug, Default, Deserialize)]
// Serde trick for adding validations via a customr deserializer, without forgoing the derive.
// See: https://github.com/serde-rs/serde/issues/1220.
Expand Down

0 comments on commit e8b8e87

Please sign in to comment.