-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow zero as gas prices #416
Conversation
eth_l1_gas_price: felt_to_u128(&block.l1_gas_price.price_in_wei).try_into().unwrap_or(NonZeroU128::MIN), | ||
strk_l1_gas_price: felt_to_u128(&block.l1_gas_price.price_in_fri).try_into().unwrap_or(NonZeroU128::MIN), | ||
eth_l1_data_gas_price: felt_to_u128(&block.l1_data_gas_price.price_in_wei) | ||
.try_into() | ||
.unwrap_or(NonZeroU128::MIN), | ||
strk_l1_data_gas_price: felt_to_u128(&block.l1_data_gas_price.price_in_fri) | ||
.try_into() | ||
.unwrap_or(NonZeroU128::MIN), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should be more careful with these checks because there are two cases that we are treating the same when we use try_into().unwrap_or(NonZeroU128::MIN)
:
- the intended case:
try_into()
errors because of the value1
- the unintended case:
try_into()
errors because the felt overflows (is> u128::MAX
)
The latter case should be handled more gracefully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch 😉 I'll fix it asap
33bb8a0
to
37f5e75
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! Left some request for changes
} | ||
|
||
// If felt_to_u128 conversion is ok, it won't fail cause we're catching the zero above | ||
Ok(NonZeroU128::new(felt_to_u128(price)?).unwrap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't handle the error gracefully?
Ok(BlockContext::new(block_info, chain_info, versioned_constants.clone(), bouncer_config)) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
|
||
use starknet::core::types::{Felt, ResourcePrice}; | ||
use starknet_api::core::ChainId; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn test_build_block_context_with_zero_gas_prices() { | ||
let chain_id = ChainId::Mainnet; | ||
// We don't really care about most of the fields. | ||
// What's important here is to set to zero different gas prices | ||
let block = BlockWithTxs { | ||
status: starknet::core::types::BlockStatus::AcceptedOnL1, | ||
block_hash: Felt::ZERO, | ||
parent_hash: Felt::ZERO, | ||
block_number: 1, | ||
new_root: Felt::ZERO, | ||
timestamp: 0, | ||
sequencer_address: Felt::ZERO, | ||
l1_gas_price: ResourcePrice { price_in_wei: Felt::ZERO, price_in_fri: Felt::ZERO }, | ||
l1_data_gas_price: ResourcePrice { price_in_wei: Felt::ZERO, price_in_fri: Felt::ZERO }, | ||
l1_da_mode: L1DataAvailabilityMode::Blob, | ||
starknet_version: String::from("0.13.2.1"), | ||
transactions: vec![], | ||
}; | ||
|
||
let starknet_version = blockifier::versioned_constants::StarknetVersion::Latest; | ||
|
||
// Call this function must not fail | ||
let block_context = build_block_context(chain_id, &block, starknet_version).unwrap(); | ||
|
||
// Verify that gas prices were set to NonZeroU128::MIN | ||
assert_eq!(block_context.block_info().gas_prices.eth_l1_gas_price, NonZeroU128::MIN); | ||
assert_eq!(block_context.block_info().gas_prices.strk_l1_gas_price, NonZeroU128::MIN); | ||
assert_eq!(block_context.block_info().gas_prices.eth_l1_data_gas_price, NonZeroU128::MIN); | ||
assert_eq!(block_context.block_info().gas_prices.strk_l1_data_gas_price, NonZeroU128::MIN); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! Could we add a test that checks that, if we have correct values, the block context is updated accordingly?
@@ -28,7 +28,7 @@ async fn test_replay_block() { | |||
let state_reader = AsyncRpcStateReader::new(rpc_client.clone(), previous_block_id); | |||
let mut state = CachedState::from(state_reader); | |||
|
|||
let block_context = build_block_context(ChainId::Sepolia, &block_with_txs, StarknetVersion::V0_13_1); | |||
let block_context = build_block_context(ChainId::Sepolia, &block_with_txs, StarknetVersion::V0_13_1).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems good for now, but the rules around zero gas are not that clear to me. If gas can actually be zero and we need to support that, then it seems the upstream GasPrices
struct should be changed to reflect this.
Problem: Gas prices can potentially be zero under certain conditions. See detailed explanation here.
Solution: Since the GasPrice struct uses NonZeroU128 types for its inner elements, we need to use a default fallback value in these cases, similar to the approach taken in Papyrus.
This can be reproduced on Sepolia for blocks 0~5 but the Starknet version from those blocks (0.12.x) is not supported by SNOS yet.
Issue Number: #405
Closes #405
Type
Description
Breaking changes?