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

Commit

Permalink
feat(execution): use gas costs only from VersionedConstants
Browse files Browse the repository at this point in the history
- Remove from constants module and replace all usages with
  `VersionedConstants#gas_cost(..)`
  - Move all comments from the constants module into the const whitelist
    in `VersionedConstants`.
- Add gas cost getter to `EntryPointExecutionContext`, for readability
  - enclose in closure inside hint_processor.rs for even more brevity.
- Move `Transaction::Initial_gas` into `VersionedConstants`: it is now
  derived from the constants json.
- No other logic changes.
  • Loading branch information
Gilad Chase committed Jan 31, 2024
1 parent f367a56 commit 8b38505
Show file tree
Hide file tree
Showing 15 changed files with 99 additions and 119 deletions.
53 changes: 0 additions & 53 deletions crates/blockifier/src/abi/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,59 +39,6 @@ pub const N_STEPS_RESOURCE: &str = "n_steps";
pub const CAIRO0_ENTRY_POINT_STRUCT_SIZE: usize = 2;
pub const N_STEPS_PER_PEDERSEN: usize = 8;

// Gas Cost.
// See documentation in core/os/constants.cairo.
pub const STEP_GAS_COST: u64 = 100;
pub const RANGE_CHECK_GAS_COST: u64 = 70;
pub const MEMORY_HOLE_GAS_COST: u64 = 10;

// An estimation of the initial gas for a transaction to run with. This solution is temporary and
// this value will become a field of the transaction.
pub const INITIAL_GAS_COST: u64 = 10_u64.pow(8) * STEP_GAS_COST;
// Compiler gas costs.
pub const ENTRY_POINT_INITIAL_BUDGET: u64 = 100 * STEP_GAS_COST;
// The initial gas budget for a system call (this value is hard-coded by the compiler).
// This needs to be high enough to cover OS costs in the case of failure due to out of gas.
pub const SYSCALL_BASE_GAS_COST: u64 = 100 * STEP_GAS_COST;
// OS gas costs.
pub const ENTRY_POINT_GAS_COST: u64 = ENTRY_POINT_INITIAL_BUDGET + 500 * STEP_GAS_COST;
pub const FEE_TRANSFER_GAS_COST: u64 = ENTRY_POINT_GAS_COST + 100 * STEP_GAS_COST;
pub const TRANSACTION_GAS_COST: u64 =
(2 * ENTRY_POINT_GAS_COST) + FEE_TRANSFER_GAS_COST + (100 * STEP_GAS_COST);
// The required gas for each syscall.
pub const CALL_CONTRACT_GAS_COST: u64 =
SYSCALL_BASE_GAS_COST + 10 * STEP_GAS_COST + ENTRY_POINT_GAS_COST;
pub const DEPLOY_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 200 * STEP_GAS_COST + ENTRY_POINT_GAS_COST;
pub const EMIT_EVENT_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 10 * STEP_GAS_COST;
pub const GET_BLOCK_HASH_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 50 * STEP_GAS_COST;
pub const GET_EXECUTION_INFO_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 10 * STEP_GAS_COST;
pub const KECCAK_GAS_COST: u64 = SYSCALL_BASE_GAS_COST;
pub const KECCAK_ROUND_COST_GAS_COST: u64 = 180000;
pub const LIBRARY_CALL_GAS_COST: u64 = CALL_CONTRACT_GAS_COST;
pub const REPLACE_CLASS_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 50 * STEP_GAS_COST;
pub const SECP256K1_ADD_GAS_COST: u64 = 406 * STEP_GAS_COST + 29 * RANGE_CHECK_GAS_COST;
pub const SECP256K1_GET_POINT_FROM_X_GAS_COST: u64 =
391 * STEP_GAS_COST + 30 * RANGE_CHECK_GAS_COST + 20 * MEMORY_HOLE_GAS_COST;
pub const SECP256K1_GET_XY_GAS_COST: u64 =
239 * STEP_GAS_COST + 11 * RANGE_CHECK_GAS_COST + 40 * MEMORY_HOLE_GAS_COST;
pub const SECP256K1_MUL_GAS_COST: u64 =
76501 * STEP_GAS_COST + 7045 * RANGE_CHECK_GAS_COST + 2 * MEMORY_HOLE_GAS_COST;
pub const SECP256K1_NEW_GAS_COST: u64 =
475 * STEP_GAS_COST + 35 * RANGE_CHECK_GAS_COST + 40 * MEMORY_HOLE_GAS_COST;
pub const SECP256R1_ADD_GAS_COST: u64 = 589 * STEP_GAS_COST + 57 * RANGE_CHECK_GAS_COST;
pub const SECP256R1_GET_POINT_FROM_X_GAS_COST: u64 =
510 * STEP_GAS_COST + 44 * RANGE_CHECK_GAS_COST + 20 * MEMORY_HOLE_GAS_COST;
pub const SECP256R1_GET_XY_GAS_COST: u64 =
241 * STEP_GAS_COST + 11 * RANGE_CHECK_GAS_COST + 40 * MEMORY_HOLE_GAS_COST;
pub const SECP256R1_MUL_GAS_COST: u64 =
125340 * STEP_GAS_COST + 13961 * RANGE_CHECK_GAS_COST + 2 * MEMORY_HOLE_GAS_COST;
pub const SECP256R1_NEW_GAS_COST: u64 =
594 * STEP_GAS_COST + 49 * RANGE_CHECK_GAS_COST + 40 * MEMORY_HOLE_GAS_COST;

pub const SEND_MESSAGE_TO_L1_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 50 * STEP_GAS_COST;
pub const STORAGE_READ_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 50 * STEP_GAS_COST;
pub const STORAGE_WRITE_GAS_COST: u64 = SYSCALL_BASE_GAS_COST + 50 * STEP_GAS_COST;

// OS reserved contract addresses.

// This contract stores the block number -> block hash mapping.
Expand Down
4 changes: 4 additions & 0 deletions crates/blockifier/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ impl BlockContext {
pub fn chain_info(&self) -> &ChainInfo {
&self.chain_info
}

pub fn versioned_constants(&self) -> &VersionedConstants {
&self.versioned_constants
}
}

impl BlockContext {
Expand Down
5 changes: 3 additions & 2 deletions crates/blockifier/src/execution/contract_address_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use starknet_api::transaction::{Calldata, ContractAddressSalt};
use starknet_api::{calldata, stark_felt};

use crate::abi::abi_utils::selector_from_name;
use crate::abi::constants;
use crate::context::ChainInfo;
use crate::execution::call_info::{CallExecution, Retdata};
use crate::execution::entry_point::CallEntryPoint;
Expand All @@ -15,6 +14,7 @@ use crate::test_utils::contracts::FeatureContract;
use crate::test_utils::dict_state_reader::DictStateReader;
use crate::test_utils::initial_test_state::test_state;
use crate::test_utils::{CairoVersion, BALANCE};
use crate::versioned_constants::VersionedConstants;

#[rstest]
fn test_calculate_contract_address() {
Expand All @@ -30,11 +30,12 @@ fn test_calculate_contract_address() {
deployer_address: ContractAddress,
state: &mut CachedState<DictStateReader>,
) {
let versioned_constants = VersionedConstants::create_for_testing();
let entry_point_call = CallEntryPoint {
calldata,
entry_point_selector: selector_from_name("test_contract_address"),
storage_address: deployer_address,
initial_gas: constants::INITIAL_GAS_COST,
initial_gas: versioned_constants.gas_cost("initial_gas_cost"),
..Default::default()
};
let contract_address =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use starknet_api::transaction::Calldata;
use starknet_api::StarknetApiError;
use thiserror::Error;

use crate::abi::constants;
use crate::block::BlockInfo;
use crate::context::TransactionContext;
use crate::execution::call_info::{CallInfo, OrderedEvent, OrderedL2ToL1Message};
Expand Down Expand Up @@ -458,7 +457,7 @@ pub fn execute_library_call(
storage_address: syscall_handler.storage_address,
caller_address: syscall_handler.caller_address,
call_type: CallType::Delegate,
initial_gas: constants::INITIAL_GAS_COST,
initial_gas: syscall_handler.context.get_gas_cost("initial_gas_cost"),
};

execute_inner_call(entry_point, vm, syscall_handler)
Expand Down
5 changes: 2 additions & 3 deletions crates/blockifier/src/execution/deprecated_syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use self::hint_processor::{
execute_inner_call, execute_library_call, felt_to_bool, read_call_params, read_calldata,
read_felt_array, DeprecatedSyscallExecutionError, DeprecatedSyscallHintProcessor,
};
use crate::abi::constants;
use crate::execution::call_info::{MessageToL1, OrderedEvent, OrderedL2ToL1Message};
use crate::execution::entry_point::{CallEntryPoint, CallType, ConstructorContext};
use crate::execution::execution_utils::{
Expand Down Expand Up @@ -201,7 +200,7 @@ pub fn call_contract(
storage_address,
caller_address: syscall_handler.storage_address,
call_type: CallType::Call,
initial_gas: constants::INITIAL_GAS_COST,
initial_gas: syscall_handler.context.get_gas_cost("initial_gas_cost"),
};
let retdata_segment = execute_inner_call(entry_point, vm, syscall_handler)?;

Expand Down Expand Up @@ -329,7 +328,7 @@ pub fn deploy(
syscall_handler.context,
ctor_context,
request.constructor_calldata,
constants::INITIAL_GAS_COST,
syscall_handler.context.get_gas_cost("initial_gas_cost"),
)?;
syscall_handler.inner_calls.push(call_info);

Expand Down
4 changes: 4 additions & 0 deletions crates/blockifier/src/execution/entry_point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ impl EntryPointExecutionContext {
.collect::<Vec<String>>()
.join("\n")
}

pub fn get_gas_cost(&self, name: &str) -> u64 {
self.tx_context.block_context.versioned_constants.gas_cost(name)
}
}

pub fn execute_constructor_entry_point(
Expand Down
5 changes: 3 additions & 2 deletions crates/blockifier/src/execution/entry_point_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use starknet_api::transaction::Calldata;
use starknet_api::{calldata, patricia_key, stark_felt};

use crate::abi::abi_utils::{get_storage_var_address, selector_from_name};
use crate::abi::constants;
use crate::context::ChainInfo;
use crate::execution::call_info::{CallExecution, CallInfo, Retdata};
use crate::execution::contract_class::ContractClass;
Expand All @@ -28,6 +27,7 @@ use crate::test_utils::{
create_calldata, trivial_external_entry_point, trivial_external_entry_point_with_address,
CairoVersion, BALANCE,
};
use crate::versioned_constants::VersionedConstants;

const INNER_CALL_CONTRACT_IN_CALL_CHAIN_OFFSET: usize = 65;

Expand Down Expand Up @@ -197,11 +197,12 @@ fn run_security_test(
entry_point_name: &str,
calldata: Calldata,
) {
let versioned_constants = VersionedConstants::create_for_testing();
let entry_point_call = CallEntryPoint {
entry_point_selector: selector_from_name(entry_point_name),
calldata,
storage_address: security_contract.get_instance_address(0),
initial_gas: constants::INITIAL_GAS_COST,
initial_gas: versioned_constants.gas_cost("initial_gas_cost"),
..Default::default()
};
let error = match entry_point_call.execute_directly(state) {
Expand Down
80 changes: 47 additions & 33 deletions crates/blockifier/src/execution/syscalls/hint_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use starknet_api::transaction::{Calldata, Resource};
use starknet_api::StarknetApiError;
use thiserror::Error;

use crate::abi::constants;
use crate::abi::sierra_types::SierraTypeError;
use crate::execution::call_info::{CallInfo, OrderedEvent, OrderedL2ToL1Message};
use crate::execution::common_hints::{ExecutionMode, HintExecutionResult};
Expand Down Expand Up @@ -229,72 +228,87 @@ impl<'a> SyscallHintProcessor<'a> {
self.increment_syscall_count(&selector);
}

let get_gas_cost = |name: &str| -> u64 { self.context.get_gas_cost(name) };
match selector {
SyscallSelector::CallContract => {
self.execute_syscall(vm, call_contract, constants::CALL_CONTRACT_GAS_COST)
self.execute_syscall(vm, call_contract, get_gas_cost("call_contract_gas_cost"))
}
SyscallSelector::Deploy => {
self.execute_syscall(vm, deploy, get_gas_cost("deploy_gas_cost"))
}
SyscallSelector::Deploy => self.execute_syscall(vm, deploy, constants::DEPLOY_GAS_COST),
SyscallSelector::EmitEvent => {
self.execute_syscall(vm, emit_event, constants::EMIT_EVENT_GAS_COST)
self.execute_syscall(vm, emit_event, get_gas_cost("emit_event_gas_cost"))
}
SyscallSelector::GetBlockHash => {
self.execute_syscall(vm, get_block_hash, constants::GET_BLOCK_HASH_GAS_COST)
self.execute_syscall(vm, get_block_hash, get_gas_cost("get_block_hash_gas_cost"))
}
SyscallSelector::GetExecutionInfo => {
self.execute_syscall(vm, get_execution_info, constants::GET_EXECUTION_INFO_GAS_COST)
SyscallSelector::GetExecutionInfo => self.execute_syscall(
vm,
get_execution_info,
get_gas_cost("get_execution_info_gas_cost"),
),
SyscallSelector::Keccak => {
self.execute_syscall(vm, keccak, get_gas_cost("keccak_gas_cost"))
}
SyscallSelector::Keccak => self.execute_syscall(vm, keccak, constants::KECCAK_GAS_COST),
SyscallSelector::LibraryCall => {
self.execute_syscall(vm, library_call, constants::LIBRARY_CALL_GAS_COST)
}
SyscallSelector::LibraryCallL1Handler => {
self.execute_syscall(vm, library_call_l1_handler, constants::LIBRARY_CALL_GAS_COST)
self.execute_syscall(vm, library_call, get_gas_cost("library_call_gas_cost"))
}
SyscallSelector::LibraryCallL1Handler => self.execute_syscall(
vm,
library_call_l1_handler,
get_gas_cost("library_call_gas_cost"),
),
SyscallSelector::ReplaceClass => {
self.execute_syscall(vm, replace_class, constants::REPLACE_CLASS_GAS_COST)
self.execute_syscall(vm, replace_class, get_gas_cost("replace_class_gas_cost"))
}
SyscallSelector::Secp256k1Add => {
self.execute_syscall(vm, secp256k1_add, constants::SECP256K1_ADD_GAS_COST)
self.execute_syscall(vm, secp256k1_add, get_gas_cost("secp256k1_add_gas_cost"))
}
SyscallSelector::Secp256k1GetPointFromX => self.execute_syscall(
vm,
secp256k1_get_point_from_x,
constants::SECP256K1_GET_POINT_FROM_X_GAS_COST,
get_gas_cost("secp256k1_get_point_from_x_gas_cost"),
),
SyscallSelector::Secp256k1GetXy => self.execute_syscall(
vm,
secp256k1_get_xy,
get_gas_cost("secp256k1_get_xy_gas_cost"),
),
SyscallSelector::Secp256k1GetXy => {
self.execute_syscall(vm, secp256k1_get_xy, constants::SECP256K1_GET_XY_GAS_COST)
}
SyscallSelector::Secp256k1Mul => {
self.execute_syscall(vm, secp256k1_mul, constants::SECP256K1_MUL_GAS_COST)
self.execute_syscall(vm, secp256k1_mul, get_gas_cost("secp256k1_mul_gas_cost"))
}
SyscallSelector::Secp256k1New => {
self.execute_syscall(vm, secp256k1_new, constants::SECP256K1_NEW_GAS_COST)
self.execute_syscall(vm, secp256k1_new, get_gas_cost("secp256k1_new_gas_cost"))
}
SyscallSelector::Secp256r1Add => {
self.execute_syscall(vm, secp256r1_add, constants::SECP256R1_ADD_GAS_COST)
self.execute_syscall(vm, secp256r1_add, get_gas_cost("secp256r1_add_gas_cost"))
}
SyscallSelector::Secp256r1GetPointFromX => self.execute_syscall(
vm,
secp256r1_get_point_from_x,
constants::SECP256R1_GET_POINT_FROM_X_GAS_COST,
get_gas_cost("secp256r1_get_point_from_x_gas_cost"),
),
SyscallSelector::Secp256r1GetXy => self.execute_syscall(
vm,
secp256r1_get_xy,
get_gas_cost("secp256r1_get_xy_gas_cost"),
),
SyscallSelector::Secp256r1GetXy => {
self.execute_syscall(vm, secp256r1_get_xy, constants::SECP256R1_GET_XY_GAS_COST)
}
SyscallSelector::Secp256r1Mul => {
self.execute_syscall(vm, secp256r1_mul, constants::SECP256R1_MUL_GAS_COST)
self.execute_syscall(vm, secp256r1_mul, get_gas_cost("secp256r1_mul_gas_cost"))
}
SyscallSelector::Secp256r1New => {
self.execute_syscall(vm, secp256r1_new, constants::SECP256R1_NEW_GAS_COST)
}
SyscallSelector::SendMessageToL1 => {
self.execute_syscall(vm, send_message_to_l1, constants::SEND_MESSAGE_TO_L1_GAS_COST)
self.execute_syscall(vm, secp256r1_new, get_gas_cost("secp256r1_new_gas_cost"))
}
SyscallSelector::SendMessageToL1 => self.execute_syscall(
vm,
send_message_to_l1,
get_gas_cost("send_message_to_l1_gas_cost"),
),
SyscallSelector::StorageRead => {
self.execute_syscall(vm, storage_read, constants::STORAGE_READ_GAS_COST)
self.execute_syscall(vm, storage_read, get_gas_cost("storage_read_gas_cost"))
}
SyscallSelector::StorageWrite => {
self.execute_syscall(vm, storage_write, constants::STORAGE_WRITE_GAS_COST)
self.execute_syscall(vm, storage_write, get_gas_cost("storage_write_gas_cost"))
}
_ => Err(HintError::UnknownHint(
format!("Unsupported syscall selector {selector:?}.").into(),
Expand Down Expand Up @@ -361,7 +375,7 @@ impl<'a> SyscallHintProcessor<'a> {
) -> SyscallResult<Response>,
{
// Refund `SYSCALL_BASE_GAS_COST` as it was pre-charged.
let required_gas = syscall_gas_cost - constants::SYSCALL_BASE_GAS_COST;
let required_gas = syscall_gas_cost - self.context.get_gas_cost("syscall_base_gas_cost");

let SyscallRequestWrapper { gas_counter, request } =
SyscallRequestWrapper::<Request>::read(vm, &mut self.syscall_ptr)?;
Expand Down
3 changes: 2 additions & 1 deletion crates/blockifier/src/execution/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,8 @@ pub fn keccak(

// TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion works.
let n_rounds_as_u64 = u64::try_from(n_rounds).expect("Failed to convert usize to u64.");
let gas_cost = n_rounds_as_u64 * constants::KECCAK_ROUND_COST_GAS_COST;
let gas_cost =
n_rounds_as_u64 * syscall_handler.context.get_gas_cost("keccak_round_cost_gas_cost");
if gas_cost > *remaining_gas {
let out_of_gas_error =
StarkFelt::try_from(OUT_OF_GAS_ERROR).map_err(SyscallExecutionError::from)?;
Expand Down
4 changes: 2 additions & 2 deletions crates/blockifier/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ use starknet_api::transaction::{
use starknet_api::{calldata, contract_address, patricia_key, stark_felt};

use crate::abi::abi_utils::{get_fee_token_var_address, selector_from_name};
use crate::abi::constants::{self};
use crate::execution::contract_class::{ContractClass, ContractClassV0};
use crate::execution::entry_point::{CallEntryPoint, CallType};
use crate::execution::execution_utils::felt_to_stark_felt;
use crate::utils::const_max;
use crate::versioned_constants::VersionedConstants;

// TODO(Dori, 1/2/2024): Remove these constants once all tests use the `contracts` and
// `initial_test_state` modules for testing.
Expand Down Expand Up @@ -212,7 +212,7 @@ pub fn trivial_external_entry_point_with_address(
storage_address: contract_address,
caller_address: ContractAddress::default(),
call_type: CallType::Call,
initial_gas: constants::INITIAL_GAS_COST,
initial_gas: VersionedConstants::create_for_account_testing().gas_cost("initial_gas_cost"),
}
}

Expand Down
6 changes: 2 additions & 4 deletions crates/blockifier/src/transaction/account_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use starknet_api::hash::StarkFelt;
use starknet_api::transaction::{Calldata, Fee, ResourceBounds, TransactionVersion};

use crate::abi::abi_utils::selector_from_name;
use crate::abi::constants as abi_constants;
use crate::context::{BlockContext, TransactionContext};
use crate::execution::call_info::{CallInfo, Retdata};
use crate::execution::contract_class::ContractClass;
Expand All @@ -30,7 +29,6 @@ use crate::transaction::objects::{
HasRelatedFeeType, TransactionExecutionInfo, TransactionExecutionResult, TransactionInfo,
TransactionInfoCreator, TransactionPreValidationResult,
};
use crate::transaction::transaction_execution::Transaction;
use crate::transaction::transaction_types::TransactionType;
use crate::transaction::transaction_utils::update_remaining_gas;
use crate::transaction::transactions::{
Expand Down Expand Up @@ -306,7 +304,7 @@ impl AccountTransaction {
caller_address: tx_info.sender_address(),
call_type: CallType::Call,
// The fee-token contract is a Cairo 0 contract, hence the initial gas is irrelevant.
initial_gas: abi_constants::INITIAL_GAS_COST,
initial_gas: block_context.versioned_constants.gas_cost("initial_gas_cost"),
};

let mut context = EntryPointExecutionContext::new_invoke(tx_context, true)?;
Expand Down Expand Up @@ -561,7 +559,7 @@ impl<S: StateReader> ExecutableTransaction<S> for AccountTransaction {
self.perform_pre_validation_stage(state, &tx_context, charge_fee, strict_nonce_check)?;

// Run validation and execution.
let mut remaining_gas = Transaction::initial_gas();
let mut remaining_gas = block_context.versioned_constants.tx_initial_gas();
let ValidateExecuteCallInfo {
validate_call_info,
execute_call_info,
Expand Down
Loading

0 comments on commit 8b38505

Please sign in to comment.