Skip to content

Commit

Permalink
build(blockifier): add l2_gas_price and refactor (#322)
Browse files Browse the repository at this point in the history
* build(blockifier): add l2_gas_price and refactor

* fix(blockifier): change l2 gas price type to nonzero u128
  • Loading branch information
aner-starkware authored Aug 25, 2024
1 parent e2bcd73 commit 72fa342
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 86 deletions.
53 changes: 49 additions & 4 deletions crates/blockifier/src/blockifier/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::abi::constants;
use crate::state::errors::StateError;
use crate::state::state_api::{State, StateResult};
use crate::transaction::objects::FeeType;
use crate::versioned_constants::{VersionedConstants, VersionedConstantsOverrides};

#[cfg(test)]
#[path = "block_test.rs"]
Expand All @@ -27,13 +28,50 @@ pub struct BlockInfo {

#[derive(Clone, Debug)]
pub struct GasPrices {
pub eth_l1_gas_price: NonZeroU128, // In wei.
pub strk_l1_gas_price: NonZeroU128, // In fri.
pub eth_l1_data_gas_price: NonZeroU128, // In wei.
pub strk_l1_data_gas_price: NonZeroU128, // In fri.
eth_l1_gas_price: NonZeroU128, // In wei.
strk_l1_gas_price: NonZeroU128, // In fri.
eth_l1_data_gas_price: NonZeroU128, // In wei.
strk_l1_data_gas_price: NonZeroU128, // In fri.
eth_l2_gas_price: NonZeroU128, // In wei.
strk_l2_gas_price: NonZeroU128, // In fri.
}

impl GasPrices {
pub fn new(
eth_l1_gas_price: NonZeroU128,
strk_l1_gas_price: NonZeroU128,
eth_l1_data_gas_price: NonZeroU128,
strk_l1_data_gas_price: NonZeroU128,
) -> Self {
// TODO(Aner): get gas prices from python.
let eth_l2_gas_price = NonZeroU128::new(
VersionedConstants::get_versioned_constants(VersionedConstantsOverrides {
validate_max_n_steps: 0,
max_recursion_depth: 0,
versioned_constants_base_overrides: None,
})
.l1_to_l2_gas_price_conversion(eth_l1_gas_price.into()),
)
.expect("L1 to L2 price conversion error (Rust side).");
let strk_l2_gas_price = NonZeroU128::new(
VersionedConstants::get_versioned_constants(VersionedConstantsOverrides {
validate_max_n_steps: 0,
max_recursion_depth: 0,
versioned_constants_base_overrides: None,
})
.l1_to_l2_gas_price_conversion(strk_l1_gas_price.into()),
)
.expect("L1 to L2 price conversion error (Rust side).");
GasPrices {
eth_l1_gas_price,
strk_l1_gas_price,
eth_l1_data_gas_price,
strk_l1_data_gas_price,
eth_l2_gas_price,
strk_l2_gas_price,
}
}

pub fn get_l1_gas_price_by_fee_type(&self, fee_type: &FeeType) -> NonZeroU128 {
match fee_type {
FeeType::Strk => self.strk_l1_gas_price,
Expand All @@ -47,6 +85,13 @@ impl GasPrices {
FeeType::Eth => self.eth_l1_data_gas_price,
}
}

pub fn get_l2_gas_price_by_fee_type(&self, fee_type: &FeeType) -> NonZeroU128 {
match fee_type {
FeeType::Strk => self.strk_l2_gas_price,
FeeType::Eth => self.eth_l2_gas_price,
}
}
}

// Block pre-processing.
Expand Down
16 changes: 13 additions & 3 deletions crates/blockifier/src/fee/fee_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,20 @@ use rstest::rstest;
use starknet_api::transaction::Fee;

use crate::abi::constants::N_STEPS_RESOURCE;
use crate::blockifier::block::GasPrices;
use crate::context::BlockContext;
use crate::fee::actual_cost::TransactionReceipt;
use crate::fee::fee_checks::{FeeCheckError, FeeCheckReportFields, PostExecutionReport};
use crate::fee::fee_utils::calculate_l1_gas_by_vm_usage;
use crate::invoke_tx_args;
use crate::test_utils::contracts::FeatureContract;
use crate::test_utils::initial_test_state::test_state;
use crate::test_utils::{CairoVersion, BALANCE};
use crate::test_utils::{
CairoVersion,
BALANCE,
DEFAULT_ETH_L1_DATA_GAS_PRICE,
DEFAULT_ETH_L1_GAS_PRICE,
};
use crate::transaction::objects::GasVector;
use crate::transaction::test_utils::{account_invoke_tx, l1_resource_bounds};
use crate::utils::u128_from_usize;
Expand Down Expand Up @@ -122,8 +128,12 @@ fn test_discounted_gas_overdraft(
#[case] expect_failure: bool,
) {
let mut block_context = BlockContext::create_for_account_testing();
block_context.block_info.gas_prices.strk_l1_gas_price = gas_price.try_into().unwrap();
block_context.block_info.gas_prices.strk_l1_data_gas_price = data_gas_price.try_into().unwrap();
block_context.block_info.gas_prices = GasPrices::new(
DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(),
gas_price.try_into().unwrap(),
DEFAULT_ETH_L1_DATA_GAS_PRICE.try_into().unwrap(),
data_gas_price.try_into().unwrap(),
);

let account = FeatureContract::AccountWithoutValidations(CairoVersion::Cairo0);
let mut state = test_state(&block_context.chain_info, BALANCE, &[(account, 1)]);
Expand Down
12 changes: 6 additions & 6 deletions crates/blockifier/src/test_utils/struct_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ impl BlockInfo {
block_number: BlockNumber(CURRENT_BLOCK_NUMBER),
block_timestamp: BlockTimestamp(CURRENT_BLOCK_TIMESTAMP),
sequencer_address: contract_address!(TEST_SEQUENCER_ADDRESS),
gas_prices: GasPrices {
eth_l1_gas_price: DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(),
strk_l1_gas_price: DEFAULT_STRK_L1_GAS_PRICE.try_into().unwrap(),
eth_l1_data_gas_price: DEFAULT_ETH_L1_DATA_GAS_PRICE.try_into().unwrap(),
strk_l1_data_gas_price: DEFAULT_STRK_L1_DATA_GAS_PRICE.try_into().unwrap(),
},
gas_prices: GasPrices::new(
DEFAULT_ETH_L1_GAS_PRICE.try_into().unwrap(),
DEFAULT_STRK_L1_GAS_PRICE.try_into().unwrap(),
DEFAULT_ETH_L1_DATA_GAS_PRICE.try_into().unwrap(),
DEFAULT_STRK_L1_DATA_GAS_PRICE.try_into().unwrap(),
),
use_kzg_da: false,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,9 @@ fn test_insufficient_max_fee_reverts(
.unwrap();
assert!(!tx_execution_info1.is_reverted());
let actual_fee_depth1 = tx_execution_info1.receipt.fee;
let gas_price = u128::from(block_context.block_info.gas_prices.strk_l1_gas_price);
let gas_price = u128::from(
block_context.block_info.gas_prices.get_l1_gas_price_by_fee_type(&FeeType::Strk),
);
let gas_ammount = u64::try_from(actual_fee_depth1.0 / gas_price).unwrap();

// Invoke the `recurse` function with depth of 2 and the actual fee of depth 1 as max_fee.
Expand Down
15 changes: 10 additions & 5 deletions crates/blockifier/src/transaction/transactions_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,8 @@ fn test_insufficient_resource_bounds(

let gas_prices = &block_context.block_info.gas_prices;
// TODO(Aner, 21/01/24) change to linear combination.
let minimal_fee = Fee(minimal_l1_gas * u128::from(gas_prices.eth_l1_gas_price));
let minimal_fee =
Fee(minimal_l1_gas * u128::from(gas_prices.get_l1_gas_price_by_fee_type(&FeeType::Eth)));
// Max fee too low (lower than minimal estimated fee).
let invalid_max_fee = Fee(minimal_fee.0 - 1);
let invalid_v1_tx = account_invoke_tx(
Expand All @@ -926,7 +927,7 @@ fn test_insufficient_resource_bounds(
);

// Test V3 transaction.
let actual_strk_l1_gas_price = gas_prices.strk_l1_gas_price;
let actual_strk_l1_gas_price = gas_prices.get_l1_gas_price_by_fee_type(&FeeType::Strk);

// Max L1 gas amount too low.
// TODO(Ori, 1/2/2024): Write an indicative expect message explaining why the conversion works.
Expand Down Expand Up @@ -993,7 +994,9 @@ fn test_actual_fee_gt_resource_bounds(
let minimal_l1_gas = estimate_minimal_gas_vector(block_context, tx).unwrap().l1_gas;
let minimal_resource_bounds = l1_resource_bounds(
u64::try_from(minimal_l1_gas).unwrap(),
u128::from(block_context.block_info.gas_prices.strk_l1_gas_price),
u128::from(
block_context.block_info.gas_prices.get_l1_gas_price_by_fee_type(&FeeType::Strk),
),
);
// The estimated minimal fee is lower than the actual fee.
let invalid_tx = account_invoke_tx(
Expand All @@ -1005,8 +1008,10 @@ fn test_actual_fee_gt_resource_bounds(
// Test error.
assert!(execution_error.starts_with("Insufficient max L1 gas:"));
// Test that fee was charged.
let minimal_fee =
Fee(minimal_l1_gas * u128::from(block_context.block_info.gas_prices.strk_l1_gas_price));
let minimal_fee = Fee(minimal_l1_gas
* u128::from(
block_context.block_info.gas_prices.get_l1_gas_price_by_fee_type(&FeeType::Strk),
));
assert_eq!(execution_result.receipt.fee, minimal_fee);
}

Expand Down
8 changes: 8 additions & 0 deletions crates/blockifier/src/versioned_constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,14 @@ impl VersionedConstants {
Self::get(StarknetVersion::Latest)
}

/// Converts from l1 gas cost to l2 gas cost with **upward rounding**
pub fn l1_to_l2_gas_price_conversion(&self, l1_gas_price: u128) -> u128 {
let l1_to_l2_gas_price_ratio: Ratio<u128> =
Ratio::new(1, u128::from(self.os_constants.gas_costs.step_gas_cost))
* self.vm_resource_fee_cost()["n_steps"];
*(l1_to_l2_gas_price_ratio * l1_gas_price).ceil().numer()
}

/// Returns the initial gas of any transaction to run with.
pub fn tx_initial_gas(&self) -> u64 {
let os_consts = &self.os_constants;
Expand Down
12 changes: 6 additions & 6 deletions crates/gateway/src/rpc_objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ impl TryInto<BlockInfo> for BlockHeader {
block_number: self.block_number,
sequencer_address: self.sequencer_address,
block_timestamp: self.timestamp,
gas_prices: GasPrices {
eth_l1_gas_price: parse_gas_price(self.l1_gas_price.price_in_wei)?,
strk_l1_gas_price: parse_gas_price(self.l1_gas_price.price_in_fri)?,
eth_l1_data_gas_price: parse_gas_price(self.l1_data_gas_price.price_in_wei)?,
strk_l1_data_gas_price: parse_gas_price(self.l1_data_gas_price.price_in_fri)?,
},
gas_prices: GasPrices::new(
parse_gas_price(self.l1_gas_price.price_in_wei)?,
parse_gas_price(self.l1_gas_price.price_in_fri)?,
parse_gas_price(self.l1_data_gas_price.price_in_wei)?,
parse_gas_price(self.l1_data_gas_price.price_in_fri)?,
),
use_kzg_da: matches!(self.l1_da_mode, L1DataAvailabilityMode::Blob),
})
}
Expand Down
72 changes: 30 additions & 42 deletions crates/native_blockifier/src/py_state_diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,48 +172,36 @@ impl TryFrom<PyBlockInfo> for BlockInfo {
block_number: BlockNumber(block_info.block_number),
block_timestamp: BlockTimestamp(block_info.block_timestamp),
sequencer_address: ContractAddress::try_from(block_info.sequencer_address.0)?,
gas_prices: GasPrices {
eth_l1_gas_price: block_info.l1_gas_price.price_in_wei.try_into().map_err(
|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidGasPriceWei(
block_info.l1_gas_price.price_in_wei,
),
)
},
)?,
strk_l1_gas_price: block_info.l1_gas_price.price_in_fri.try_into().map_err(
|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidGasPriceFri(
block_info.l1_gas_price.price_in_fri,
),
)
},
)?,
eth_l1_data_gas_price: block_info
.l1_data_gas_price
.price_in_wei
.try_into()
.map_err(|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidDataGasPriceWei(
block_info.l1_data_gas_price.price_in_wei,
),
)
})?,
strk_l1_data_gas_price: block_info
.l1_data_gas_price
.price_in_fri
.try_into()
.map_err(|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidDataGasPriceFri(
block_info.l1_data_gas_price.price_in_fri,
),
)
})?,
},
gas_prices: GasPrices::new(
block_info.l1_gas_price.price_in_wei.try_into().map_err(|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidGasPriceWei(
block_info.l1_gas_price.price_in_wei,
),
)
})?,
block_info.l1_gas_price.price_in_fri.try_into().map_err(|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidGasPriceFri(
block_info.l1_gas_price.price_in_fri,
),
)
})?,
block_info.l1_data_gas_price.price_in_wei.try_into().map_err(|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidDataGasPriceWei(
block_info.l1_data_gas_price.price_in_wei,
),
)
})?,
block_info.l1_data_gas_price.price_in_fri.try_into().map_err(|_| {
NativeBlockifierInputError::InvalidNativeBlockifierInputError(
InvalidNativeBlockifierInputError::InvalidDataGasPriceFri(
block_info.l1_data_gas_price.price_in_fri,
),
)
})?,
),
use_kzg_da: block_info.use_kzg_da,
})
}
Expand Down
16 changes: 6 additions & 10 deletions crates/papyrus_execution/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,16 +359,12 @@ fn create_block_context(
use_kzg_da,
block_number,
// TODO(yair): What to do about blocks pre 0.13.1 where the data gas price were 0?
gas_prices: GasPrices {
eth_l1_gas_price: NonZeroU128::new(l1_gas_price.price_in_wei.0)
.unwrap_or(NonZeroU128::MIN),
strk_l1_gas_price: NonZeroU128::new(l1_gas_price.price_in_fri.0)
.unwrap_or(NonZeroU128::MIN),
eth_l1_data_gas_price: NonZeroU128::new(l1_data_gas_price.price_in_wei.0)
.unwrap_or(NonZeroU128::MIN),
strk_l1_data_gas_price: NonZeroU128::new(l1_data_gas_price.price_in_fri.0)
.unwrap_or(NonZeroU128::MIN),
},
gas_prices: GasPrices::new(
NonZeroU128::new(l1_gas_price.price_in_wei.0).unwrap_or(NonZeroU128::MIN),
NonZeroU128::new(l1_gas_price.price_in_fri.0).unwrap_or(NonZeroU128::MIN),
NonZeroU128::new(l1_data_gas_price.price_in_wei.0).unwrap_or(NonZeroU128::MIN),
NonZeroU128::new(l1_data_gas_price.price_in_fri.0).unwrap_or(NonZeroU128::MIN),
),
};
let chain_info = ChainInfo {
chain_id,
Expand Down
27 changes: 18 additions & 9 deletions crates/papyrus_execution/src/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use blockifier::execution::call_info::{
Retdata as BlockifierRetdata,
};
use blockifier::execution::entry_point::CallType as BlockifierCallType;
use blockifier::transaction::objects::{GasVector, TransactionExecutionInfo};
use blockifier::transaction::objects::{FeeType, GasVector, TransactionExecutionInfo};
use cairo_vm::types::builtin_name::BuiltinName;
use cairo_vm::vm::runners::cairo_runner::ExecutionResources as VmExecutionResources;
use indexmap::IndexMap;
Expand Down Expand Up @@ -153,16 +153,16 @@ pub(crate) fn tx_execution_output_to_fee_estimation(
block_context: &BlockContext,
) -> ExecutionResult<FeeEstimation> {
let gas_prices = &block_context.block_info().gas_prices;
let (gas_price, data_gas_price) = match tx_execution_output.price_unit {
PriceUnit::Wei => (
GasPrice(gas_prices.eth_l1_gas_price.get()),
GasPrice(gas_prices.eth_l1_data_gas_price.get()),
let (gas_price, data_gas_price) = (
GasPrice(
gas_prices.get_l1_gas_price_by_fee_type(&tx_execution_output.price_unit.into()).get(),
),
PriceUnit::Fri => (
GasPrice(gas_prices.strk_l1_gas_price.get()),
GasPrice(gas_prices.strk_l1_data_gas_price.get()),
GasPrice(
gas_prices
.get_l1_data_gas_price_by_fee_type(&tx_execution_output.price_unit.into())
.get(),
),
};
);

let gas_vector = tx_execution_output.execution_info.receipt.gas;

Expand Down Expand Up @@ -521,3 +521,12 @@ pub enum PriceUnit {
/// Fri.
Fri,
}

impl From<PriceUnit> for FeeType {
fn from(value: PriceUnit) -> Self {
match value {
PriceUnit::Wei => FeeType::Eth,
PriceUnit::Fri => FeeType::Strk,
}
}
}

0 comments on commit 72fa342

Please sign in to comment.