Skip to content

Commit

Permalink
feat: l2 gas cli argument (#287)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeapoz authored May 22, 2024
1 parent d396b76 commit e009070
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 39 deletions.
7 changes: 6 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use clap::{Parser, Subcommand, ValueEnum};
use colored::Colorize;
use fork::{ForkDetails, ForkSource};
use logging_middleware::LoggingMiddleware;
use node::ShowCalls;
use node::{ShowCalls, DEFAULT_L2_GAS_PRICE};
use observability::LogLevel;
use tracing_subscriber::filter::LevelFilter;

Expand Down Expand Up @@ -232,6 +232,10 @@ struct Cli {
/// Show Gas details information
show_gas_details: ShowGasDetails,

#[arg(long, default_value_t = DEFAULT_L2_GAS_PRICE)]
/// If provided, uses a custom value as the L2 gas price.
l2_gas_price: u64,

#[arg(long)]
/// If true, the tool will try to contact openchain to resolve the ABI & topic names.
/// It will make debug log more readable, but will decrease the performance.
Expand Down Expand Up @@ -360,6 +364,7 @@ async fn main() -> anyhow::Result<()> {
fork_details,
Some(observability),
InMemoryNodeConfig {
l2_gas_price: opt.l2_gas_price,
show_calls: opt.show_calls,
show_outputs: opt.show_outputs,
show_storage_logs: opt.show_storage_logs,
Expand Down
20 changes: 13 additions & 7 deletions src/node/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{
filters::{FilterType, LogFilter},
fork::ForkSource,
namespaces::{EthNamespaceT, EthTestNodeNamespaceT, RpcResult},
node::{InMemoryNode, TransactionResult, L2_GAS_PRICE, MAX_TX_SIZE, PROTOCOL_VERSION},
node::{InMemoryNode, TransactionResult, MAX_TX_SIZE, PROTOCOL_VERSION},
utils::{self, h256_to_u64, into_jsrpc_error, not_implemented, IntoBoxedFuture},
};

Expand Down Expand Up @@ -610,7 +610,12 @@ impl<S: ForkSource + std::fmt::Debug + Clone + Send + Sync + 'static> EthNamespa

/// Returns the current gas price in U256 format.
fn gas_price(&self) -> RpcResult<U256> {
let fair_l2_gas_price: u64 = L2_GAS_PRICE;
let fair_l2_gas_price: u64 = self
.get_inner()
.read()
.expect("Failed to acquire read lock")
.fee_input_provider
.l2_gas_price;
Ok(U256::from(fair_l2_gas_price)).into_boxed_future()
}

Expand Down Expand Up @@ -1332,7 +1337,8 @@ impl<S: ForkSource + std::fmt::Debug + Clone + Send + Sync + 'static> EthNamespa
// Can't be more than the total number of blocks
.clamp(1, reader.current_miniblock + 1);

let mut base_fee_per_gas = vec![U256::from(L2_GAS_PRICE); block_count as usize];
let mut base_fee_per_gas =
vec![U256::from(reader.fee_input_provider.l2_gas_price); block_count as usize];

let oldest_block = reader.current_miniblock + 1 - base_fee_per_gas.len() as u64;
// We do not store gas used ratio for blocks, returns array of zeroes as a placeholder.
Expand Down Expand Up @@ -1474,7 +1480,7 @@ mod tests {
cache::CacheConfig,
fork::ForkDetails,
http_fork_source::HttpForkSource,
node::{compute_hash, InMemoryNode, Snapshot},
node::{compute_hash, InMemoryNode, Snapshot, DEFAULT_L2_GAS_PRICE},
testing::{
self, default_tx_debug_info, ForkBlockConfig, LogBuilder, MockServer,
TransactionResponseBuilder,
Expand Down Expand Up @@ -1513,7 +1519,7 @@ mod tests {
);
assert_eq!(
fee_history.base_fee_per_gas,
vec![U256::from(L2_GAS_PRICE); 2]
vec![U256::from(DEFAULT_L2_GAS_PRICE); 2]
);
assert_eq!(fee_history.gas_used_ratio, vec![0.0]);
assert_eq!(fee_history.reward, Some(vec![vec![U256::from(0); 3]]));
Expand All @@ -1534,7 +1540,7 @@ mod tests {
);
assert_eq!(
fee_history.base_fee_per_gas,
vec![U256::from(L2_GAS_PRICE); 2]
vec![U256::from(DEFAULT_L2_GAS_PRICE); 2]
);
assert_eq!(fee_history.gas_used_ratio, vec![0.0]);
assert_eq!(fee_history.reward, Some(vec![vec![]]));
Expand Down Expand Up @@ -1565,7 +1571,7 @@ mod tests {
);
assert_eq!(
fee_history.base_fee_per_gas,
vec![U256::from(L2_GAS_PRICE); 3]
vec![U256::from(DEFAULT_L2_GAS_PRICE); 3]
);
assert_eq!(fee_history.gas_used_ratio, vec![0.0, 0.0]);
assert_eq!(fee_history.reward, Some(vec![vec![U256::from(0); 3]; 2]));
Expand Down
32 changes: 19 additions & 13 deletions src/node/fee_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,37 @@ use zksync_node_fee_model::BatchFeeModelInputProvider;
use zksync_types::fee_model::{FeeModelConfigV2, FeeParams, FeeParamsV2};
use zksync_types::L1_GAS_PER_PUBDATA_BYTE;

pub const CONFIG: FeeModelConfigV2 = FeeModelConfigV2 {
minimal_l2_gas_price: 20_000_000,
compute_overhead_part: 0.0,
pubdata_overhead_part: 1.0,
batch_overhead_l1_gas: 800000,
max_gas_per_batch: 200000000,
max_pubdata_per_batch: 100000,
};

#[derive(Debug, Clone, PartialEq)]
pub struct TestNodeFeeInputProvider {
l1_gas_price: u64,
pub l1_gas_price: u64,
pub l2_gas_price: u64,
}

impl TestNodeFeeInputProvider {
pub fn new(l1_gas_price: u64) -> Self {
Self { l1_gas_price }
pub fn new(l1_gas_price: u64, l2_gas_price: u64) -> Self {
Self {
l1_gas_price,
l2_gas_price,
}
}

pub fn get_fee_model_config(&self) -> FeeModelConfigV2 {
FeeModelConfigV2 {
minimal_l2_gas_price: self.l2_gas_price,
compute_overhead_part: 0.0,
pubdata_overhead_part: 1.0,
batch_overhead_l1_gas: 800000,
max_gas_per_batch: 200000000,
max_pubdata_per_batch: 100000,
}
}
}

impl BatchFeeModelInputProvider for TestNodeFeeInputProvider {
fn get_fee_model_params(&self) -> FeeParams {
// TODO: consider using old fee model for the olds blocks, when forking
FeeParams::V2(FeeParamsV2 {
config: CONFIG,
config: self.get_fee_model_config(),
l1_gas_price: self.l1_gas_price,
l1_pubdata_price: self.l1_gas_price * L1_GAS_PER_PUBDATA_BYTE as u64,
})
Expand Down
68 changes: 52 additions & 16 deletions src/node/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ use crate::{
filters::EthFilters,
fork::{block_on, ForkDetails, ForkSource, ForkStorage},
formatter,
node::{
fee_model::{TestNodeFeeInputProvider, CONFIG},
storage_logs::print_storage_logs_details,
},
node::{fee_model::TestNodeFeeInputProvider, storage_logs::print_storage_logs_details},
observability::Observability,
system_contracts::{self, SystemContracts},
utils::{bytecode_to_factory_dep, create_debug_output, into_jsrpc_error, to_human_size},
Expand Down Expand Up @@ -79,8 +76,8 @@ pub const TEST_NODE_NETWORK_ID: u32 = 260;
/// L1 Gas Price.
pub const L1_GAS_PRICE: u64 = 50_000_000_000;
// TODO: for now, that's fine, as computation overhead is set to zero, but we may consider using calculated fee input everywhere.
/// L2 Gas Price.
pub const L2_GAS_PRICE: u64 = 25_000_000;
/// The default L2 Gas Price to be used if not supplied via the CLI argument.
pub const DEFAULT_L2_GAS_PRICE: u64 = 25_000_000;
/// L1 Gas Price Scale Factor for gas estimation.
pub const ESTIMATE_GAS_PRICE_SCALE_FACTOR: f64 = 1.5;
/// Acceptable gas overestimation limit.
Expand Down Expand Up @@ -882,8 +879,10 @@ pub struct Snapshot {
}

/// Defines the configuration parameters for the [InMemoryNode].
#[derive(Default, Debug, Clone)]
#[derive(Debug, Clone)]
pub struct InMemoryNodeConfig {
// The values to be used when calculating gas.
pub l2_gas_price: u64,
pub show_calls: ShowCalls,
pub show_outputs: bool,
pub show_storage_logs: ShowStorageLogs,
Expand All @@ -893,6 +892,21 @@ pub struct InMemoryNodeConfig {
pub system_contracts_options: system_contracts::Options,
}

impl Default for InMemoryNodeConfig {
fn default() -> Self {
Self {
l2_gas_price: DEFAULT_L2_GAS_PRICE,
show_calls: Default::default(),
show_outputs: Default::default(),
show_storage_logs: Default::default(),
show_vm_details: Default::default(),
show_gas_details: Default::default(),
resolve_hashes: Default::default(),
system_contracts_options: Default::default(),
}
}
}

/// In-memory node, that can be used for local & unit testing.
/// It also supports the option of forking testnet/mainnet.
/// All contents are removed when object is destroyed.
Expand Down Expand Up @@ -938,7 +952,10 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
current_batch: f.l1_block.0,
current_miniblock: f.l2_miniblock,
current_miniblock_hash: f.l2_miniblock_hash,
fee_input_provider: TestNodeFeeInputProvider::new(f.l1_gas_price),
fee_input_provider: TestNodeFeeInputProvider::new(
f.l1_gas_price,
config.l2_gas_price,
),
tx_results: Default::default(),
blocks,
block_hashes,
Expand Down Expand Up @@ -972,7 +989,10 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
current_batch: 0,
current_miniblock: 0,
current_miniblock_hash: block_hash,
fee_input_provider: TestNodeFeeInputProvider::new(L1_GAS_PRICE),
fee_input_provider: TestNodeFeeInputProvider::new(
L1_GAS_PRICE,
config.l2_gas_price,
),
tx_results: Default::default(),
blocks,
block_hashes,
Expand Down Expand Up @@ -1243,10 +1263,20 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
)
);

tracing::info!(
"Publishing full block costs the operator around {} l2 gas",
to_human_size(bootloader_debug.gas_per_pubdata * CONFIG.batch_overhead_l1_gas),
);
{
let fee_model_config = self
.inner
.read()
.expect("Failed to acquire reading lock")
.fee_input_provider
.get_fee_model_config();
tracing::info!(
"Publishing full block costs the operator around {} l2 gas",
to_human_size(
bootloader_debug.gas_per_pubdata * fee_model_config.batch_overhead_l1_gas
),
);
}
tracing::info!("Your transaction has contributed to filling up the block in the following way (we take the max contribution as the cost):");
tracing::info!(
" Length overhead: {:>15}",
Expand Down Expand Up @@ -1277,7 +1307,13 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
return Err("exceeds block gas limit".into());
}

if tx.common_data.fee.max_fee_per_gas < L2_GAS_PRICE.into() {
let l2_gas_price = self
.inner
.read()
.expect("failed acquiring reader")
.fee_input_provider
.l2_gas_price;
if tx.common_data.fee.max_fee_per_gas < l2_gas_price.into() {
tracing::info!(
"Submitted Tx is Unexecutable {:?} because of MaxFeePerGasTooLow {}",
tx.hash(),
Expand Down Expand Up @@ -1619,7 +1655,7 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
} else {
U64::from(1)
},
effective_gas_price: Some(L2_GAS_PRICE.into()),
effective_gas_price: Some(inner.fee_input_provider.l2_gas_price.into()),
..Default::default()
};
let debug = create_debug_output(&l2_tx, &result, call_traces).expect("create debug output"); // OK to unwrap here as Halt is handled above
Expand Down Expand Up @@ -1771,7 +1807,7 @@ mod tests {
async fn test_run_l2_tx_validates_tx_max_fee_per_gas_too_low() {
let node = InMemoryNode::<HttpForkSource>::default();
let tx = testing::TransactionBuilder::new()
.set_max_fee_per_gas(U256::from(L2_GAS_PRICE - 1))
.set_max_fee_per_gas(U256::from(DEFAULT_L2_GAS_PRICE - 1))
.build();
node.set_rich_account(tx.common_data.initiator_address);

Expand Down
4 changes: 2 additions & 2 deletions src/node/zks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use zksync_web3_decl::error::Web3Error;
use crate::{
fork::ForkSource,
namespaces::{RpcResult, ZksNamespaceT},
node::{InMemoryNode, TransactionResult, L2_GAS_PRICE},
node::{InMemoryNode, TransactionResult},
utils::{
internal_error, into_jsrpc_error, not_implemented, utc_datetime_from_epoch_ms,
IntoBoxedFuture,
Expand Down Expand Up @@ -382,7 +382,7 @@ impl<S: ForkSource + std::fmt::Debug + Clone + Send + Sync + 'static> ZksNamespa
execute_tx_hash: None,
executed_at: None,
l1_gas_price: 0,
l2_fair_gas_price: L2_GAS_PRICE,
l2_fair_gas_price: reader.fee_input_provider.l2_gas_price,
base_system_contracts_hashes: reader
.system_contracts
.baseline_contracts
Expand Down

0 comments on commit e009070

Please sign in to comment.