From ecb8d5467fdbee2d70c2ee272f1f7a5335b370aa Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 11 Jan 2024 13:16:38 +0100 Subject: [PATCH 1/2] add pessimistic overhead for L1->L2 transactions --- .../src/api_server/tx_sender/mod.rs | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/core/lib/zksync_core/src/api_server/tx_sender/mod.rs b/core/lib/zksync_core/src/api_server/tx_sender/mod.rs index c1a983182f9f..0a5396aa4bf0 100644 --- a/core/lib/zksync_core/src/api_server/tx_sender/mod.rs +++ b/core/lib/zksync_core/src/api_server/tx_sender/mod.rs @@ -17,6 +17,7 @@ use zksync_types::{ fee::{Fee, TransactionExecutionMetrics}, fee_model::BatchFeeInput, get_code_key, get_intrinsic_constants, + l1::is_l1_tx_type, l2::{error::TxCheckError::TxDuplication, L2Tx}, utils::storage_key_for_eth_balance, AccountTreeId, Address, ExecuteTransactionCommon, L2ChainId, Nonce, PackedEthSignature, @@ -815,7 +816,9 @@ impl TxSender { result.into_api_call_result()?; self.ensure_tx_executable(tx.clone(), &tx_metrics, false)?; - let overhead = derive_overhead( + // Now, we need to calculate the final overhead for the transaction. We need to take into accoutn the fact + // that the migration of 1.4.1 may be still going on. + let overhead = derive_pessimistic_overhead( suggested_gas_limit, gas_per_pubdata_byte as u32, tx.encoding_len(), @@ -925,3 +928,40 @@ impl TxSender { Ok(()) } } + +/// During switch to the 1.4.1 protocol version, there will be a moment of discrepancy, when while +/// the L2 has already upgraded to 1.4.1 (and thus suggests smaller overhead), the L1 is still on the previous version. +/// +/// This might lead to situations when L1->L2 transactions estimated with the new versions would work on the state keeper side, +/// but they won't even make it there, but the protection mechanisms for L1->L2 transactions will reject them on L1. +/// TODO(X): remove this function after the upgrade is complete +fn derive_pessimistic_overhead( + gas_limit: u32, + gas_price_per_pubdata: u32, + encoded_len: usize, + tx_type: u8, + vm_version: VmVersion, +) -> u32 { + let current_overhead = derive_overhead( + gas_limit, + gas_price_per_pubdata, + encoded_len, + tx_type, + vm_version, + ); + + if is_l1_tx_type(tx_type) { + // We are in the L1->L2 transaction, so we need to account for the fact that the L1 is still on the previous version. + // We assume that the overhead will be the same as for the previous version. + let previous_overhead = derive_overhead( + gas_limit, + gas_price_per_pubdata, + encoded_len, + tx_type, + VmVersion::VmBoojumIntegration, + ); + current_overhead.max(previous_overhead) + } else { + current_overhead + } +} From 1d4f57789f1aa3325240cdb985cbb11deb876dc6 Mon Sep 17 00:00:00 2001 From: Stanislav Breadless Date: Thu, 11 Jan 2024 14:45:38 +0100 Subject: [PATCH 2/2] add a new config param --- core/bin/external_node/src/config/mod.rs | 16 ++++++++++ core/lib/config/src/configs/api.rs | 9 ++++++ core/lib/env_config/src/api.rs | 2 ++ .../src/api_server/tx_sender/mod.rs | 31 ++++++++++++++----- etc/env/base/api.toml | 1 + 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/core/bin/external_node/src/config/mod.rs b/core/bin/external_node/src/config/mod.rs index f32c8bc9affc..6bf06f049303 100644 --- a/core/bin/external_node/src/config/mod.rs +++ b/core/bin/external_node/src/config/mod.rs @@ -142,6 +142,15 @@ pub struct OptionalENConfig { /// The max possible number of gas that `eth_estimateGas` is allowed to overestimate. #[serde(default = "OptionalENConfig::default_estimate_gas_acceptable_overestimation")] pub estimate_gas_acceptable_overestimation: u32, + /// Whether to use the compatibility mode for gas estimation for L1->L2 transactions. + /// During the migration to the 1.4.1 fee model, there will be a period, when the server + /// will already have the 1.4.1 fee model, while the L1 contracts will still expect the transactions + /// to use the previous fee model with much higher overhead. + /// + /// When set to `true`, the API will ensure to return gasLimit is high enough overhead for both the old + /// and the new fee model when estimating L1->L2 transactions. + #[serde(default = "OptionalENConfig::default_l1_to_l2_transactions_compatibility_mode")] + pub l1_to_l2_transactions_compatibility_mode: bool, /// The multiplier to use when suggesting gas price. Should be higher than one, /// otherwise if the L1 prices soar, the suggested gas price won't be sufficient to be included in block #[serde(default = "OptionalENConfig::default_gas_price_scale_factor")] @@ -214,6 +223,10 @@ impl OptionalENConfig { 1_000 } + const fn default_l1_to_l2_transactions_compatibility_mode() -> bool { + true + } + const fn default_gas_price_scale_factor() -> f64 { 1.2 } @@ -521,6 +534,9 @@ impl From for TxSenderConfig { max_allowed_l2_tx_gas_limit: u32::MAX, validation_computational_gas_limit: u32::MAX, chain_id: config.remote.l2_chain_id, + l1_to_l2_transactions_compatibility_mode: config + .optional + .l1_to_l2_transactions_compatibility_mode, } } } diff --git a/core/lib/config/src/configs/api.rs b/core/lib/config/src/configs/api.rs index 609634d6f34a..a06b9fa53dfe 100644 --- a/core/lib/config/src/configs/api.rs +++ b/core/lib/config/src/configs/api.rs @@ -51,6 +51,14 @@ pub struct Web3JsonRpcConfig { pub estimate_gas_scale_factor: f64, /// The max possible number of gas that `eth_estimateGas` is allowed to overestimate. pub estimate_gas_acceptable_overestimation: u32, + /// Whether to use the compatibility mode for gas estimation for L1->L2 transactions. + /// During the migration to the 1.4.1 fee model, there will be a period, when the server + /// will already have the 1.4.1 fee model, while the L1 contracts will still expect the transactions + /// to use the previous fee model with much higher overhead. + /// + /// When set to `true`, the API will ensure to return gasLimit is high enough overhead for both the old + /// and the new fee model when estimating L1->L2 transactions. + pub l1_to_l2_transactions_compatibility_mode: bool, /// Max possible size of an ABI encoded tx (in bytes). pub max_tx_size: usize, /// Max number of cache misses during one VM execution. If the number of cache misses exceeds this value, the API server panics. @@ -101,6 +109,7 @@ impl Web3JsonRpcConfig { account_pks: Default::default(), estimate_gas_scale_factor: 1.2, estimate_gas_acceptable_overestimation: 1000, + l1_to_l2_transactions_compatibility_mode: true, max_tx_size: 1000000, vm_execution_cache_misses_limit: Default::default(), vm_concurrency_limit: Default::default(), diff --git a/core/lib/env_config/src/api.rs b/core/lib/env_config/src/api.rs index 3bffb281ad5c..5368122437ff 100644 --- a/core/lib/env_config/src/api.rs +++ b/core/lib/env_config/src/api.rs @@ -75,6 +75,7 @@ mod tests { estimate_gas_scale_factor: 1.0f64, gas_price_scale_factor: 1.2, estimate_gas_acceptable_overestimation: 1000, + l1_to_l2_transactions_compatibility_mode: true, max_tx_size: 1000000, vm_execution_cache_misses_limit: None, vm_concurrency_limit: Some(512), @@ -119,6 +120,7 @@ mod tests { API_WEB3_JSON_RPC_ACCOUNT_PKS="0x0000000000000000000000000000000000000000000000000000000000000001,0x0000000000000000000000000000000000000000000000000000000000000002" API_WEB3_JSON_RPC_ESTIMATE_GAS_SCALE_FACTOR=1.0 API_WEB3_JSON_RPC_ESTIMATE_GAS_ACCEPTABLE_OVERESTIMATION=1000 + API_WEB3_JSON_RPC_L1_TO_L2_TRANSACTIONS_COMPATIBILITY_MODE=true API_WEB3_JSON_RPC_MAX_TX_SIZE=1000000 API_WEB3_JSON_RPC_VM_CONCURRENCY_LIMIT=512 API_WEB3_JSON_RPC_FACTORY_DEPS_CACHE_SIZE_MB=128 diff --git a/core/lib/zksync_core/src/api_server/tx_sender/mod.rs b/core/lib/zksync_core/src/api_server/tx_sender/mod.rs index 0a5396aa4bf0..2477edceb17a 100644 --- a/core/lib/zksync_core/src/api_server/tx_sender/mod.rs +++ b/core/lib/zksync_core/src/api_server/tx_sender/mod.rs @@ -212,6 +212,7 @@ pub struct TxSenderConfig { pub max_allowed_l2_tx_gas_limit: u32, pub vm_execution_cache_misses_limit: Option, pub validation_computational_gas_limit: u32, + pub l1_to_l2_transactions_compatibility_mode: bool, pub chain_id: L2ChainId, } @@ -229,6 +230,8 @@ impl TxSenderConfig { vm_execution_cache_misses_limit: web3_json_config.vm_execution_cache_misses_limit, validation_computational_gas_limit: state_keeper_config .validation_computational_gas_limit, + l1_to_l2_transactions_compatibility_mode: web3_json_config + .l1_to_l2_transactions_compatibility_mode, chain_id, } } @@ -818,13 +821,27 @@ impl TxSender { // Now, we need to calculate the final overhead for the transaction. We need to take into accoutn the fact // that the migration of 1.4.1 may be still going on. - let overhead = derive_pessimistic_overhead( - suggested_gas_limit, - gas_per_pubdata_byte as u32, - tx.encoding_len(), - tx.tx_format() as u8, - protocol_version.into(), - ); + let overhead = if self + .0 + .sender_config + .l1_to_l2_transactions_compatibility_mode + { + derive_pessimistic_overhead( + suggested_gas_limit, + gas_per_pubdata_byte as u32, + tx.encoding_len(), + tx.tx_format() as u8, + protocol_version.into(), + ) + } else { + derive_overhead( + suggested_gas_limit, + gas_per_pubdata_byte as u32, + tx.encoding_len(), + tx.tx_format() as u8, + protocol_version.into(), + ) + }; let full_gas_limit = match tx_body_gas_limit.overflowing_add(gas_for_bytecodes_pubdata + overhead) { diff --git a/etc/env/base/api.toml b/etc/env/base/api.toml index 186e2cfb2b0e..1c5d906603fb 100644 --- a/etc/env/base/api.toml +++ b/etc/env/base/api.toml @@ -17,6 +17,7 @@ pubsub_polling_interval=200 threads_per_server=128 max_nonce_ahead=50 gas_price_scale_factor=1.2 +l1_to_l2_transactions_compatibility_mode=true request_timeout=10 account_pks=[ "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",