diff --git a/src/main.rs b/src/main.rs index 4550d9c6..9f34103e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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; @@ -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. @@ -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, diff --git a/src/node/eth.rs b/src/node/eth.rs index 1d2d329b..aeb61750 100644 --- a/src/node/eth.rs +++ b/src/node/eth.rs @@ -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}, }; @@ -610,7 +610,12 @@ impl EthNamespa /// Returns the current gas price in U256 format. fn gas_price(&self) -> RpcResult { - 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() } @@ -1332,7 +1337,8 @@ impl 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. @@ -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, @@ -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]])); @@ -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![]])); @@ -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])); diff --git a/src/node/fee_model.rs b/src/node/fee_model.rs index dedbeb81..88e7bf3a 100644 --- a/src/node/fee_model.rs +++ b/src/node/fee_model.rs @@ -3,23 +3,29 @@ 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, + } } } @@ -27,7 +33,7 @@ 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, }) diff --git a/src/node/in_memory.rs b/src/node/in_memory.rs index 5e558dd1..9da07315 100644 --- a/src/node/in_memory.rs +++ b/src/node/in_memory.rs @@ -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}, @@ -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. @@ -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, @@ -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. @@ -938,7 +952,10 @@ impl InMemoryNode { 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, @@ -972,7 +989,10 @@ impl InMemoryNode { 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, @@ -1243,10 +1263,20 @@ impl InMemoryNode { ) ); - 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}", @@ -1277,7 +1307,13 @@ impl InMemoryNode { 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(), @@ -1619,7 +1655,7 @@ impl InMemoryNode { } 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 @@ -1771,7 +1807,7 @@ mod tests { async fn test_run_l2_tx_validates_tx_max_fee_per_gas_too_low() { let node = InMemoryNode::::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); diff --git a/src/node/zks.rs b/src/node/zks.rs index eb4486b0..b34c8831 100644 --- a/src/node/zks.rs +++ b/src/node/zks.rs @@ -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, @@ -382,7 +382,7 @@ impl 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