diff --git a/basic_bootloader/Cargo.toml b/basic_bootloader/Cargo.toml index d43b9c252..70d77b60c 100644 --- a/basic_bootloader/Cargo.toml +++ b/basic_bootloader/Cargo.toml @@ -57,8 +57,6 @@ fusaka-blobs = ["zk_ee/fusaka-blobs"] fusaka = ["pectra", "eip-7825", "eip-7934", "eip-7918", "zk_ee/eip-7825", "basic_system/fusaka"] burn_base_fee = [] cycle_marker = ["system_hooks/cycle_marker", "cycle_marker/log_to_file"] -resources_for_tester = [] -unlimited_native = [] disable_system_contracts = [] error_origins = ["zk_ee/error_origins"] delegation = ["zk_ee/delegation", "evm_interpreter/delegation", "system_hooks/delegation", "basic_system/delegation"] diff --git a/basic_bootloader/src/bootloader/block_flow/zk/mod.rs b/basic_bootloader/src/bootloader/block_flow/zk/mod.rs index 3086df820..6b0b62dd1 100644 --- a/basic_bootloader/src/bootloader/block_flow/zk/mod.rs +++ b/basic_bootloader/src/bootloader/block_flow/zk/mod.rs @@ -65,24 +65,19 @@ where "Block blob gas limit reached, invalidating transaction\n" ); Err(InvalidTransaction::BlockBlobGasLimitReached) - } else if !cfg!(feature = "resources_for_tester") - && computational_native_used > MAX_NATIVE_COMPUTATIONAL - { - // ZKsync OS-specific resources are not checked for evm tester + } else if computational_native_used > MAX_NATIVE_COMPUTATIONAL { system_log!( system, "Block native limit reached, invalidating transaction\n" ); Err(InvalidTransaction::BlockNativeLimitReached) - } else if !cfg!(feature = "resources_for_tester") && pubdata_used > system.get_pubdata_limit() { - // ZKsync OS-specific resources are not checked for evm tester + } else if pubdata_used > system.get_pubdata_limit() { system_log!( system, "Block pubdata limit reached, invalidating transaction\n" ); Err(InvalidTransaction::BlockPubdataLimitReached) - } else if !cfg!(feature = "resources_for_tester") && logs_used > MAX_NUMBER_OF_LOGS { - // ZKsync OS-specific resources are not checked for evm tester + } else if logs_used > MAX_NUMBER_OF_LOGS { system_log!( system, "Block logs limit reached, invalidating transaction\n" diff --git a/basic_bootloader/src/bootloader/constants.rs b/basic_bootloader/src/bootloader/constants.rs index ce18c7e02..f637d5a8d 100644 --- a/basic_bootloader/src/bootloader/constants.rs +++ b/basic_bootloader/src/bootloader/constants.rs @@ -72,11 +72,6 @@ pub const CALLDATA_TOKEN_GAS_COST: u64 = 4; /// EIP-7623 minimal "token" cost pub const TOTAL_COST_FLOOR_PER_TOKEN: u64 = 10; -/// EVM tester requires a high native_per_gas, but it hard-codes -/// low gas prices. We need to bypass the usual way to compute this -/// value. The value is so high because of modexp tests. -pub const TESTER_NATIVE_PER_GAS: u64 = 25_000; - // Default native price for L1->L2 transactions. // TODO (EVM-1157): find a reasonable value for it. pub const L1_TX_NATIVE_PRICE: U256 = U256::from_limbs([10, 0, 0, 0]); diff --git a/basic_bootloader/src/bootloader/errors.rs b/basic_bootloader/src/bootloader/errors.rs index 778364880..33c1faf4e 100644 --- a/basic_bootloader/src/bootloader/errors.rs +++ b/basic_bootloader/src/bootloader/errors.rs @@ -71,8 +71,6 @@ pub enum InvalidTransaction { AccessListNotSupported, /// Unacceptable pubdata price. PubdataPriceTooHigh, - /// Block gas limit is too high. - BlockGasLimitTooHigh, /// Protocol upgrade tx should be first in the block. UpgradeTxNotFirst, /// Bootloader received insufficient fees diff --git a/basic_bootloader/src/bootloader/mod.rs b/basic_bootloader/src/bootloader/mod.rs index cefd8e3e8..27ce65409 100644 --- a/basic_bootloader/src/bootloader/mod.rs +++ b/basic_bootloader/src/bootloader/mod.rs @@ -88,7 +88,6 @@ where S::Allocator::default(), )?; - // we will model initial calldata buffer as just another "heap" let mut system: System = System::init_from_metadata_and_oracle(metadata, oracle)?; let mut system_functions = HooksStorage::new_in(system.get_allocator()); diff --git a/basic_bootloader/src/bootloader/transaction/rlp_encoded/transaction.rs b/basic_bootloader/src/bootloader/transaction/rlp_encoded/transaction.rs index 84488f4b5..1559af52d 100644 --- a/basic_bootloader/src/bootloader/transaction/rlp_encoded/transaction.rs +++ b/basic_bootloader/src/bootloader/transaction/rlp_encoded/transaction.rs @@ -26,7 +26,8 @@ pub struct RlpEncodedTransaction { // time. tx_hash: Option, // Note: this field is not the recovered signer, but rather an address - // passed by oracle. Needs to be checked to be equal to recovered address. + // passed by oracle. Needs to be checked to be equal to recovered address + // in untrusted environments, e.g. proving mode from: B160, } diff --git a/basic_bootloader/src/bootloader/transaction_flow/gas_helpers.rs b/basic_bootloader/src/bootloader/transaction_flow/gas_helpers.rs index 2f7272ddf..18343cd4b 100644 --- a/basic_bootloader/src/bootloader/transaction_flow/gas_helpers.rs +++ b/basic_bootloader/src/bootloader/transaction_flow/gas_helpers.rs @@ -21,157 +21,6 @@ use zk_ee::system::{Computational, Ergs, Resources}; use zk_ee::system::{Resource, MAX_NATIVE_COMPUTATIONAL}; use zk_ee::system_log; -/// Policy trait for handling arithmetic validation errors during resource creation. -/// -/// This trait allows L1 and L2 transactions to handle errors differently: -/// - L1: Only returns internal errors (validation errors are logged and saturated) -/// - L2: Returns both validation and internal errors -pub trait ResourcesCreationErrorPolicy { - /// The return error type for create_resources_for_tx. - /// For L1: BootloaderSubsystemError (no validation errors possible) - /// For L2: TxError (both validation and internal errors) - type Error; - - /// The error type that describes arithmetic validation failures. - /// For L1: a descriptive enum for logging - /// For L2: InvalidTransaction - type ArithmeticError; - - /// Create an error for native limit underflow - fn native_underflow_error(operation: &'static str) -> Self::ArithmeticError; - - /// Create an error for intrinsic gas exceeding gas limit - fn intrinsic_gas_overflow_error( - intrinsic_overhead: u64, - gas_limit: u64, - ) -> Self::ArithmeticError; - - /// Handle an arithmetic validation error. - /// For L1: logs the error and returns Ok(saturated_value) - /// For L2: returns Err(Self::Error) - fn handle_arithmetic_error( - system: &mut System, - error: Self::ArithmeticError, - ) -> Result; - - /// Convert an internal error to the policy's error type - #[allow(dead_code)] // Reserved for future use if internal errors are added - fn from_internal_error(error: BootloaderSubsystemError) -> Self::Error; - - /// Convert a validation error to the policy's error type. - /// For L1: should never be called (deployment checks don't apply) - /// For L2: wraps in TxError::Validation - fn from_validation_error(error: InvalidTransaction) -> Self::Error; -} - -/// Arithmetic error descriptor for L1 transactions -#[derive(Debug)] -pub enum L1ArithmeticError { - /// Native limit underflow during an operation - NativeUnderflow { operation: &'static str }, - /// Gas limit is less than intrinsic gas overhead - IntrinsicGasOverflow { - intrinsic_overhead: u64, - gas_limit: u64, - }, -} - -/// Resource creation policy for L1 transactions: log and saturate on errors -pub struct L1ResourcesPolicy; - -impl ResourcesCreationErrorPolicy for L1ResourcesPolicy { - type Error = BootloaderSubsystemError; - type ArithmeticError = L1ArithmeticError; - - fn native_underflow_error(operation: &'static str) -> Self::ArithmeticError { - L1ArithmeticError::NativeUnderflow { operation } - } - - fn intrinsic_gas_overflow_error( - intrinsic_overhead: u64, - gas_limit: u64, - ) -> Self::ArithmeticError { - L1ArithmeticError::IntrinsicGasOverflow { - intrinsic_overhead, - gas_limit, - } - } - - fn handle_arithmetic_error( - system: &mut System, - error: Self::ArithmeticError, - ) -> Result { - match error { - L1ArithmeticError::NativeUnderflow { operation } => { - system_log!( - system, - "Native underflow during {}, saturating to 0 for L1 tx", - operation - ); - Ok(0) - } - L1ArithmeticError::IntrinsicGasOverflow { - intrinsic_overhead, - gas_limit, - } => { - system_log!( - system, - "Gas limit {} < intrinsic gas {} for L1 tx, saturating to 0", - gas_limit, - intrinsic_overhead - ); - Ok(0) - } - } - } - - fn from_internal_error(error: BootloaderSubsystemError) -> Self::Error { - error - } - - fn from_validation_error(error: InvalidTransaction) -> Self::Error { - // L1 transactions never have deployment validation, so this should never be called - unreachable!( - "L1ResourcesPolicy should never encounter validation error: {:?}", - error - ) - } -} - -/// Resource creation policy for L2 transactions: fail on arithmetic errors -pub struct L2ResourcesPolicy; - -impl ResourcesCreationErrorPolicy for L2ResourcesPolicy { - type Error = TxError; - type ArithmeticError = InvalidTransaction; - - fn native_underflow_error(_operation: &'static str) -> Self::ArithmeticError { - InvalidTransaction::OutOfNativeResourcesDuringValidation - } - - fn intrinsic_gas_overflow_error( - _intrinsic_overhead: u64, - _gas_limit: u64, - ) -> Self::ArithmeticError { - InvalidTransaction::OutOfGasDuringValidation - } - - fn handle_arithmetic_error( - _system: &mut System, - error: Self::ArithmeticError, - ) -> Result { - Err(TxError::Validation(error)) - } - - fn from_internal_error(error: BootloaderSubsystemError) -> Self::Error { - TxError::Internal(error) - } - - fn from_validation_error(error: InvalidTransaction) -> Self::Error { - TxError::Validation(error) - } -} - pub struct ResourcesForTx { // Resources to run the transaction. // These will be capped to MAX_NATIVE_COMPUTATIONAL, to prevent @@ -180,8 +29,6 @@ pub struct ResourcesForTx { /// Resources in excess of MAX_NATIVE_COMPUTATIONAL. /// These resources can only be used for paying for pubdata. pub withheld: S::Resources, - /// Computational native charged for as intrinsic - pub intrinsic_computational_native_charged: u64, } impl core::fmt::Debug for ResourcesForTx { @@ -190,10 +37,6 @@ impl core::fmt::Debug for ResourcesForTx { .field("gas", &(self.main_resources.ergs().0 / ERGS_PER_GAS)) .field("main_resources", &self.main_resources) .field("withheld", &self.withheld) - .field( - "intrinsic_computational_native_charged", - &self.intrinsic_computational_native_charged, - ) .finish() } } @@ -262,12 +105,7 @@ pub fn calculate_l1_tx_intrinsic_computational_native_resources(calldata_byte_le /// This function used both for L1 and L2 transactions. /// /// Computes the analogue of revm's `intrinsic_cost`: the gas that must be -/// pre-charged before the transaction body runs. Per EIP-2930/EIP-7702 the -/// per-address, per-storage-key and per-authorization costs are part of this -/// intrinsic gas. Moving them into this helper means the inner access-list / -/// authorization-list processors only need to account for native resources — -/// gas is already deducted from `main_resources` when the tx's resources are -/// materialized. +/// pre-charged before the transaction body runs. pub fn calculate_tx_intrinsic_gas( calldata_len: u64, calldata_tokens: u64, @@ -328,15 +166,13 @@ pub fn calculate_l2_tx_intrinsic_pubdata(authorization_list_num: u64, is_service } /// -/// Create initial resources for a transaction. +/// Create initial resources for a transaction, applying all three intrinsic +/// charges (pubdata, computational native, gas) in u64 arithmetic. /// -/// The `P` parameter controls how arithmetic validation errors are handled: -/// - Use `L1ResourcesPolicy` for L1 transactions: logs and saturates (never fails validation) -/// Returns `Result<..., BootloaderSubsystemError>` - validation errors are impossible -/// - Use `L2ResourcesPolicy` for L2 transactions: returns validation errors -/// Returns `Result<..., TxError>` - can fail with validation or internal errors -pub fn create_resources_for_tx>( - system: &mut System, +/// Charges are saturating: on underflow the running counter goes to 0, the +/// first observed failure is recorded, and remaining charges still apply. +/// +pub fn create_resources_for_tx( gas_limit: u64, free_native: bool, native_prepaid_from_gas: u64, @@ -344,86 +180,76 @@ pub fn create_resources_for_tx Result, P::Error> +) -> (ResourcesForTx, Option) where S::Metadata: ZkSpecificMetadata, { - // This is the real limit, which we later use to compute native_used. - // From it, we discount intrinsic pubdata and then take the min - // with the MAX_NATIVE_COMPUTATIONAL. - // We do those operations in that order because the pubdata charge - // isn't computational. - // We can consider in the future to keep two limits, so that pubdata - // is not charged from computational resource. - // Note: for zero gas price, we use "unlimited native" - let native_limit = if cfg!(feature = "unlimited_native") || free_native { - u64::MAX - 1 // So any saturation below can not be subtracted from it + let mut first_error: Option = None; + + // Gross native budget. + let native_limit = if free_native { + u64::MAX - 1 // So any saturating subtraction below cannot underflow it } else { native_prepaid_from_gas }; - // Charge intrinsic pubdata + // Charge intrinsic pubdata. Subtracted from the total native budget + // before splitting into main / withheld. let intrinsic_pubdata_overhead = native_per_pubdata_byte.saturating_mul(intrinsic_pubdata); let native_limit = match native_limit.checked_sub(intrinsic_pubdata_overhead) { Some(val) => val, - None => P::handle_arithmetic_error( - system, - P::native_underflow_error("subtracting pubdata overhead"), - )?, + None => { + first_error.get_or_insert(InvalidTransaction::OutOfNativeResourcesDuringValidation); + 0 + } }; - // EVM tester requires high native limits, so for it we never hold off resources. - // But for the real world, we bound the available resources. - - #[cfg(feature = "resources_for_tester")] - let withheld = S::Resources::from_ergs(Ergs::empty()); - - #[cfg(not(feature = "resources_for_tester"))] + // Split: anything above MAX_NATIVE_COMPUTATIONAL goes into `withheld` + // (only spendable on pubdata at refund time). let (native_limit, withheld) = if native_limit <= MAX_NATIVE_COMPUTATIONAL { (native_limit, S::Resources::from_ergs(Ergs::empty())) } else { - let withheld = + let withheld_native = <::Resources as Resources>::Native::from_computational( native_limit - MAX_NATIVE_COMPUTATIONAL, ); - ( MAX_NATIVE_COMPUTATIONAL, - S::Resources::from_native(withheld), + S::Resources::from_native(withheld_native), ) }; - // Charge intrinsic computational native + // Charge intrinsic computational native against the post-split main budget. let native_limit = match native_limit.checked_sub(intrinsic_computational_native) { Some(val) => val, - None => P::handle_arithmetic_error( - system, - P::native_underflow_error("subtracting intrinsic computational native"), - )?, + None => { + first_error.get_or_insert(InvalidTransaction::OutOfNativeResourcesDuringValidation); + 0 + } }; - let native_limit = <::Resources as Resources>::Native::from_computational( native_limit, ); - // Check if intrinsic gas exceeds gas limit + // Charge intrinsic gas against gas_limit. let gas_limit_for_tx = match gas_limit.checked_sub(intrinsic_gas) { Some(val) => val, - None => P::handle_arithmetic_error( - system, - P::intrinsic_gas_overflow_error(intrinsic_gas, gas_limit), - )?, + None => { + first_error.get_or_insert(InvalidTransaction::OutOfGasDuringValidation); + 0 + } }; + let ergs = gas_limit_for_tx.saturating_mul(ERGS_PER_GAS); - let ergs = gas_limit_for_tx.saturating_mul(ERGS_PER_GAS); // we checked at the very start that gas_limit * ERGS_PER_GAS doesn't overflow let main_resources = S::Resources::from_ergs_and_native(Ergs(ergs), native_limit); - - Ok(ResourcesForTx { - main_resources, - withheld, - intrinsic_computational_native_charged: intrinsic_computational_native, - }) + ( + ResourcesForTx { + main_resources, + withheld, + }, + first_error, + ) } /// diff --git a/basic_bootloader/src/bootloader/transaction_flow/refund_calculation.rs b/basic_bootloader/src/bootloader/transaction_flow/refund_calculation.rs index fa9dd7879..13974c56e 100644 --- a/basic_bootloader/src/bootloader/transaction_flow/refund_calculation.rs +++ b/basic_bootloader/src/bootloader/transaction_flow/refund_calculation.rs @@ -55,29 +55,30 @@ pub(crate) fn compute_gas_refund( #[allow(unused_mut)] let mut gas_used = core::cmp::max(gas_used, minimal_gas_used); - // Note: for zero gas price, we use "unlimited native" - let full_native_limit = if cfg!(feature = "unlimited_native") || native_per_gas == 0 { + // When the chain doesn't price native (`native_per_gas == 0`), the user's + // budget is treated as unlimited and the gas-from-native correction below + // is a no-op (`checked_div` returns None). + let full_native_limit = if native_per_gas == 0 { u64::MAX - 1 } else { gas_limit.saturating_mul(native_per_gas) }; let native_used = full_native_limit.saturating_sub(resources.native().remaining().as_u64()); - #[cfg(not(feature = "unlimited_native"))] - { - // Adjust gas_used with difference with used native - let delta_gas = native_used - .checked_div(native_per_gas) - .map(|q| q as i64 - gas_used as i64) - .unwrap_or(0); + // Adjust gas_used with difference with used native. With `native_per_gas == 0` + // the division returns None and `delta_gas` falls back to 0 — i.e. no + // correction when native is unpriced. + let delta_gas = native_used + .checked_div(native_per_gas) + .map(|q| q as i64 - gas_used as i64) + .unwrap_or(0); - if delta_gas > 0 { - // In this case, the native resource consumption is more than the - // gas consumption accounted for. Consume extra gas. - gas_used += delta_gas as u64; - } - // TODO: return delta_gas to gas_used? + if delta_gas > 0 { + // In this case, the native resource consumption is more than the + // gas consumption accounted for. Consume extra gas. + gas_used += delta_gas as u64; } + // TODO: return delta_gas to gas_used? let total_gas_refund = gas_limit - gas_used; system_log!(system, "Refund after accounting for unused gas, refund counters and native cost: {total_gas_refund}\n"); diff --git a/basic_bootloader/src/bootloader/transaction_flow/zk/mod.rs b/basic_bootloader/src/bootloader/transaction_flow/zk/mod.rs index 9b44db99f..67397f1aa 100644 --- a/basic_bootloader/src/bootloader/transaction_flow/zk/mod.rs +++ b/basic_bootloader/src/bootloader/transaction_flow/zk/mod.rs @@ -130,6 +130,12 @@ pub struct TxContextForPreAndPostProcessing { /// recovered by subtracting the residual from `FORMAL_INFINITE` and /// compared against the formula as an upper bound. pub intrinsic_resources: S::Resources, + /// Intrinsic computational native that was precharged against + /// `resources.main_resources` during validation. Recorded here so + /// `after_execution` can add it back when computing the total + /// `computational_native_used`, and so `verify_intrinsic_native` can + /// compare actual consumption against the formula. + pub intrinsic_computational_native: u64, /// Number of EIP-7702 authorization list entries in the transaction. /// Used by `verify_intrinsic_native` to skip the overcharging check when /// authorizations are present (failed auths consume much less native than @@ -157,6 +163,10 @@ impl core::fmt::Debug for TxContextForPreAndPostProcessing .field("total_pubdata", &self.total_pubdata) .field("native_used", &self.native_used) .field("intrinsic_resources", &self.intrinsic_resources) + .field( + "intrinsic_computational_native", + &self.intrinsic_computational_native, + ) .field("authorization_list_num", &self.authorization_list_num) .field( "statement_versioned_hashes_num", @@ -558,15 +568,14 @@ where _transaction_data_keeper: &mut impl BlockTransactionsDataKeeper, _tracer: &mut impl Tracer, ) -> Self::ExecutionResult<'a> { - // Add back the intrinsic native charged in get_resources_for_tx, - // as initial_resources doesn't include them. + // Add back as initial_resources doesn't include the intrinsic. let computational_native_used = context .resources_before_refund .clone() .diff(context.initial_resources.clone()) .native() .as_u64() - .saturating_add(context.resources.intrinsic_computational_native_charged); + .saturating_add(context.intrinsic_computational_native); #[cfg(not(target_arch = "riscv32"))] cycle_marker::log_marker( @@ -930,7 +939,7 @@ where let initial = S::Resources::FORMAL_INFINITE.native().as_u64(); let remaining = context.intrinsic_resources.native().as_u64(); let actual_used = initial.saturating_sub(remaining); - let formula = context.resources.intrinsic_computational_native_charged; + let formula = context.intrinsic_computational_native; system_log!( system, "intrinsic native verification: formula={}, actually_used={}\n", diff --git a/basic_bootloader/src/bootloader/transaction_flow/zk/process_l1_transaction.rs b/basic_bootloader/src/bootloader/transaction_flow/zk/process_l1_transaction.rs index aef32dbd5..8b3188fa9 100644 --- a/basic_bootloader/src/bootloader/transaction_flow/zk/process_l1_transaction.rs +++ b/basic_bootloader/src/bootloader/transaction_flow/zk/process_l1_transaction.rs @@ -10,7 +10,7 @@ use crate::bootloader::transaction::abi_encoded::AbiEncodedTransaction; use crate::bootloader::transaction_flow::gas_helpers::{ calculate_l1_tx_intrinsic_computational_native_resources, calculate_tx_intrinsic_gas, check_enough_resources_for_pubdata, create_resources_for_tx, - get_resources_to_charge_for_pubdata, L1ResourcesPolicy, ResourcesForTx, + get_resources_to_charge_for_pubdata, ResourcesForTx, }; use crate::bootloader::transaction_flow::refund_calculation::{compute_gas_refund, RefundInfo}; use crate::bootloader::transaction_flow::{ExecutionOutput, ExecutionResult}; @@ -107,11 +107,11 @@ where ResourcesForTx { main_resources: mut resources, withheld: withheld_resources, - intrinsic_computational_native_charged, }, native_per_gas, native_per_pubdata, minimal_gas_used, + intrinsic_computational_native, } = prepare_and_check_resources::( system, transaction, @@ -370,13 +370,13 @@ where )?; } - // Add back the intrinsic native charged in get_resources_for_tx, - // as initial_resources doesn't include them. + // Add back the intrinsic native charged in `prepare_and_check_resources`, + // as `initial_resources` is snapshotted after that precharge. let computational_native_used = resources_before_refund .diff(initial_resources) .native() .as_u64() - + intrinsic_computational_native_charged; + + intrinsic_computational_native; // Restore the saved returndata into the return buffer so that the // ExecutionResult can borrow it with the correct lifetime. @@ -417,6 +417,11 @@ struct ResourceAndFeeInfo { native_per_pubdata: u64, native_per_gas: u64, minimal_gas_used: u64, + /// Intrinsic computational native that was precharged during resource + /// preparation. Hoisted out so callers can add it back to the total + /// `computational_native_used` reported at end-of-tx (since + /// `initial_resources` is captured after the precharge). + intrinsic_computational_native: u64, } /// @@ -514,10 +519,8 @@ where let intrinsic_computational_native = calculate_l1_tx_intrinsic_computational_native_resources( transaction.calldata().len() as u64, ); - // With L1ResourcesPolicy, this returns Result, BootloaderSubsystemError> - // Validation errors are type-safe impossible - they're logged and saturated instead - let resources = create_resources_for_tx::( - system, + + let (resources, charge_err) = create_resources_for_tx::( gas_limit, native_per_gas == 0, native_prepaid_from_gas, @@ -525,7 +528,16 @@ where intrinsic_gas, intrinsic_computational_native, intrinsic_pubdata, - )?; + ); + // We are not invalidating L1 txs in case of there is not enough resources to cover intrinsic costs. + // It shouldn't be reachable in practice, as we checking it on l1, but we want to be extra safe. + if let Some(e) = charge_err { + system_log!( + system, + "L1 tx: intrinsic charge underflow ({:?}), saturating\n", + e + ); + } // L1 transactions might have a gas limit < minimal_gas_used. This should be // prevented by L1 validation, but we log and saturate if it happens. @@ -543,6 +555,7 @@ where native_per_pubdata, native_per_gas, minimal_gas_used, + intrinsic_computational_native, }) } diff --git a/basic_bootloader/src/bootloader/transaction_flow/zk/validation_impl.rs b/basic_bootloader/src/bootloader/transaction_flow/zk/validation_impl.rs index c5472ee34..a175619ab 100644 --- a/basic_bootloader/src/bootloader/transaction_flow/zk/validation_impl.rs +++ b/basic_bootloader/src/bootloader/transaction_flow/zk/validation_impl.rs @@ -7,7 +7,7 @@ use crate::bootloader::transaction::rlp_encoded::AccessListForAddress; use crate::bootloader::transaction::{charge_keccak, Transaction}; use crate::bootloader::transaction_flow::gas_helpers::{ calculate_l2_tx_intrinsic_computational_native_resources, calculate_l2_tx_intrinsic_pubdata, - calculate_tx_intrinsic_gas, create_resources_for_tx, get_gas_price, L2ResourcesPolicy, + calculate_tx_intrinsic_gas, create_resources_for_tx, get_gas_price, }; use crate::bootloader::BasicBootloaderExecutionConfig; use crate::require; @@ -36,11 +36,10 @@ use zk_ee::{internal_error, out_of_native_resources}; use zk_ee::{utils::*, wrap_error}; /// -/// Will perform basic validation, namely - checking signature, minimal resource requirements for transaction validity, -/// and will pre-charge sender to cover worst case cost. It may perform IO if needed to e.g. warm up some storage slots, +/// Will perform basic validation, namely - checking signature, minimal resource requirements for transaction validity. +/// It may perform IO if needed to e.g. warm up some storage slots, /// or mark delegation /// -/// NOTE: This function will open and close IO frame pub(crate) fn validate_and_compute_fee_for_transaction< S: EthereumLikeTypes, Config: BasicBootloaderExecutionConfig, @@ -72,25 +71,14 @@ where let calldata = transaction.calldata(); - // Validate block-level invariants (for non-service transactions) + // Validate that the transaction's gas limit is not larger than max gas limit if !transaction.is_service() { - { - // Validate that the transaction's gas limit is not larger than - // the block's gas limit. - let block_gas_limit = system.get_gas_limit(); - // First, check block gas limit can be represented as ergs. - require!( - block_gas_limit <= MAX_BLOCK_GAS_LIMIT, - InvalidTransaction::BlockGasLimitTooHigh, - system - )?; - let individual_limit = system.get_individual_tx_gas_limit(); - require!( - tx_gas_limit <= individual_limit, - InvalidTransaction::CallerGasLimitMoreThanTxLimit, - system - )?; - } + let individual_limit = system.get_individual_tx_gas_limit(); + require!( + tx_gas_limit <= individual_limit, + InvalidTransaction::CallerGasLimitMoreThanTxLimit, + system + )?; } // EIP-7623 @@ -117,29 +105,26 @@ where )? }; - let native_per_gas = { - if native_price.is_zero() { - return Err(internal_error!("Native price cannot be 0").into()); - } - - if cfg!(feature = "resources_for_tester") { - crate::bootloader::constants::TESTER_NATIVE_PER_GAS - } else if Config::SIMULATION && gas_price.is_zero() { - // For simulation, if gas price isn't set, we use base fee - // for native calculation - u256_try_to_u64(&system.get_eip1559_basefee().div_ceil(native_price)).ok_or( - TxError::Validation(InvalidTransaction::NativeResourcesAreTooExpensive), - )? - } else { - u256_try_to_u64(&gas_price.div_ceil(native_price)).ok_or(TxError::Validation( - InvalidTransaction::NativeResourcesAreTooExpensive, - ))? - } + // `native_price == 0` means the chain doesn't price native. Downstream + // treats `native_per_gas == 0` as "unlimited native budget" + let native_per_gas = if native_price.is_zero() { + 0u64 + } else if Config::SIMULATION && gas_price.is_zero() { + // For simulation, if gas price isn't set, we use base fee + // for native calculation + u256_try_to_u64(&system.get_eip1559_basefee().div_ceil(native_price)).ok_or( + TxError::Validation(InvalidTransaction::NativeResourcesAreTooExpensive), + )? + } else { + u256_try_to_u64(&gas_price.div_ceil(native_price)).ok_or(TxError::Validation( + InvalidTransaction::NativeResourcesAreTooExpensive, + ))? }; - - // We checked native_price != 0 above - let native_per_pubdata = u256_try_to_u64(&pubdata_price.wrapping_div(native_price)) - .ok_or(TxError::Validation(InvalidTransaction::PubdataPriceTooHigh))?; + // If native resources are free (native_price == 0), pubdata is free too: + // `checked_div` returns `None` and we fall back to 0. + let native_per_pubdata = + u256_try_to_u64(&pubdata_price.checked_div(native_price).unwrap_or_default()) + .ok_or(TxError::Validation(InvalidTransaction::PubdataPriceTooHigh))?; let native_prepaid_from_gas = native_per_gas.saturating_mul(tx_gas_limit); let statement_versioned_hashes_num = transaction .statement_versioned_hashes() @@ -194,9 +179,9 @@ where let intrinsic_pubdata = calculate_l2_tx_intrinsic_pubdata(authorization_list_num, transaction.is_service()); - // Now we will materialize resources, from which we will try to charge intrinsic cost on top. - let tx_resources = create_resources_for_tx::( - system, + // Materialize the tx's resource budget and charge the intrinsic overheads. + // Underflow on any of the charges surfaces as a validation error + let (tx_resources, charge_err) = create_resources_for_tx::( tx_gas_limit, native_per_gas == 0, native_prepaid_from_gas, @@ -204,7 +189,10 @@ where intrinsic_gas, intrinsic_computational_native, intrinsic_pubdata, - )?; + ); + if let Some(e) = charge_err { + return Err(TxError::Validation(e)); + } system_log!( system, @@ -535,6 +523,7 @@ where initial_resources: S::Resources::empty(), resources_before_refund: S::Resources::empty(), intrinsic_resources, + intrinsic_computational_native, authorization_list_num, statement_versioned_hashes_num, }) @@ -558,9 +547,9 @@ pub(crate) fn compute_calldata_tokens( #[cfg(feature = "eip-7623")] { let floor_tokens_gas_cost = num_tokens.saturating_mul(TOTAL_COST_FLOOR_PER_TOKEN); - let intrinsic_gas = TX_INTRINSIC_GAS.saturating_add(floor_tokens_gas_cost); + let floor_gas = TX_INTRINSIC_GAS.saturating_add(floor_tokens_gas_cost); - (num_tokens, intrinsic_gas) + (num_tokens, floor_gas) } #[cfg(not(feature = "eip-7623"))] diff --git a/basic_system/src/system_functions/keccak256.rs b/basic_system/src/system_functions/keccak256.rs index ed5aab609..63591a535 100644 --- a/basic_system/src/system_functions/keccak256.rs +++ b/basic_system/src/system_functions/keccak256.rs @@ -33,6 +33,8 @@ pub fn keccak256_native_cost_u64(len: usize) -> u64 { keccak256_native_cost_for_rounds_u64(rounds) } +// Note: `#[inline(never)]` is required, otherwise compiler produces signed multiplication instruction. +#[inline(never)] pub const fn keccak256_native_cost_for_rounds_u64(rounds: usize) -> u64 { (rounds as u64) * KECCAK256_ROUND_NATIVE_COST + KECCAK256_BASE_NATIVE_COST } diff --git a/bench_scripts/bench.sh b/bench_scripts/bench.sh index 8bd8e9f7f..2d94c0489 100755 --- a/bench_scripts/bench.sh +++ b/bench_scripts/bench.sh @@ -9,16 +9,16 @@ BLOCKS_DIR="$REPO_ROOT/tests/instances/eth_runner/blocks" # Use the first available block for quick mode QUICK_BLOCK="$(ls "$BLOCKS_DIR" | head -1)" -FEATURES="rig/no_print,rig/cycle_marker,rig/unlimited_native" +FEATURES="rig/no_print,rig/cycle_marker" # Osaka block fixtures need the fusaka + latest-BPO blob schedule on the host. if grep -q '^fusaka-blobs = ' "$REPO_ROOT/tests/instances/eth_runner/Cargo.toml"; then FEATURES="$FEATURES,fusaka,fusaka-blobs" fi -PRECOMPILE_FEATURES="rig/no_print,precompiles/cycle_marker,rig/unlimited_native" +PRECOMPILE_FEATURES="rig/no_print,precompiles/cycle_marker" if grep -q "for-tests-benchmarking-pectra" "$REPO_ROOT/zksync_os/dump_bin.sh"; then - FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker,system_hooks_tests/pectra,rig/unlimited_native" + FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker,system_hooks_tests/pectra" else - FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker,rig/unlimited_native" + FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker" fi ETH_RUNNER_MANIFEST="$REPO_ROOT/tests/instances/eth_runner/Cargo.toml" PRECOMPILE_MANIFEST="$REPO_ROOT/tests/instances/precompiles/Cargo.toml" diff --git a/bench_scripts/run_bench_side.sh b/bench_scripts/run_bench_side.sh index f6121230b..71038ef47 100755 --- a/bench_scripts/run_bench_side.sh +++ b/bench_scripts/run_bench_side.sh @@ -44,14 +44,14 @@ else PROFILE="--release" fi if grep -q "for-tests-benchmarking-pectra" zksync_os/dump_bin.sh; then - PRECOMPILES_FEATURES="rig/no_print,precompiles/cycle_marker,precompiles/pectra,rig/unlimited_native" + PRECOMPILES_FEATURES="rig/no_print,precompiles/cycle_marker,precompiles/pectra" PRECOMPILES_TESTS="test_precompiles test_pectra_precompiles test_kzg_regression" else - PRECOMPILES_FEATURES="rig/no_print,precompiles/cycle_marker,rig/unlimited_native" + PRECOMPILES_FEATURES="rig/no_print,precompiles/cycle_marker" PRECOMPILES_TESTS="test_precompiles" fi -EVM_FEATURES="rig/no_print,rig/cycle_marker,rig/unlimited_native" +EVM_FEATURES="rig/no_print,rig/cycle_marker" # The block fixtures are post-BPO Osaka blocks, so the eth_runner host must use # the fusaka + latest-BPO blob schedule. The `fusaka`/`fusaka-blobs` eth_runner # features were introduced on the PR side; guard so a pre-fusaka merge-base @@ -60,9 +60,9 @@ if grep -q '^fusaka-blobs = ' tests/instances/eth_runner/Cargo.toml; then EVM_FEATURES="$EVM_FEATURES,fusaka,fusaka-blobs" fi if grep -q "for-tests-benchmarking-pectra" zksync_os/dump_bin.sh; then - FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker,system_hooks_tests/pectra,rig/unlimited_native" + FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker,system_hooks_tests/pectra" else - FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker,rig/unlimited_native" + FRI_PRECOMPILE_FEATURES="rig/no_print,system_hooks_tests/cycle_marker" fi # Block runs are independent — outputs are namespaced by ${SIDE}_${blk} and diff --git a/forward_system/Cargo.toml b/forward_system/Cargo.toml index 663e54bb6..12520d96a 100644 --- a/forward_system/Cargo.toml +++ b/forward_system/Cargo.toml @@ -41,7 +41,6 @@ testing = ["zk_ee/testing", "evm_interpreter/testing", "basic_system/testing", " default = ["testing"] error_origins = ["zk_ee/error_origins"] no_print = [] -unlimited_native = ["basic_bootloader/unlimited_native"] # A feature for every specific use case @@ -51,8 +50,8 @@ production = ["basic_bootloader/eip-7702", "system_hooks/p256_precompile"] # Features used for tests. for_tests = ["production", "basic_bootloader/eip-4844"] -# Features used for eth_runner -eth_runner = ["basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "unlimited_native","basic_bootloader/burn_base_fee", "basic_bootloader/eip-4844"] +# Features used for eth_runner. +eth_runner = ["basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "basic_bootloader/burn_base_fee", "basic_bootloader/eip-4844"] # Additional features used for eth_stf in eth_runner eth_stf = ["basic_bootloader/eip-7702","basic_bootloader/eip-7623", "system_hooks/bls12_381", "system_hooks/blake2f", "evm_interpreter/bls12_381", "evm_interpreter/blake2f"] @@ -67,7 +66,7 @@ fusaka = ["pectra", "basic_bootloader/fusaka", "evm_interpreter/clz"] fusaka-blobs = ["basic_bootloader/fusaka-blobs"] # Features used for evm_tester -evm_tester = ["basic_bootloader/resources_for_tester", "basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "basic_bootloader/eip-7702", "system_hooks/p256_precompile", "basic_bootloader/burn_base_fee", "system_hooks/mock-unsupported-precompiles", "unlimited_native", "basic_bootloader/eip-4844"] +evm_tester = ["basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "basic_bootloader/eip-7702", "system_hooks/p256_precompile", "basic_bootloader/burn_base_fee", "system_hooks/mock-unsupported-precompiles", "basic_bootloader/eip-4844"] # Features used for evm_tester with Pectra hardfork evm_tester_pectra = ["evm_tester", "pectra"] @@ -75,9 +74,5 @@ evm_tester_pectra = ["evm_tester", "pectra"] # Features used for evm_tester with Fusaka hardfork evm_tester_fusaka = ["evm_tester", "fusaka"] -# Features used for legacy evm_tester. Only defined in forward system, -# as the legacy evm_tester does not perform a proof run. -evm_tester_legacy = ["basic_bootloader/resources_for_tester", "basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "basic_bootloader/eip-7702", "basic_bootloader/burn_base_fee", "system_hooks/mock-unsupported-precompiles", "unlimited_native"] - [dev-dependencies] tempfile = "3" diff --git a/forward_system/src/run/convert.rs b/forward_system/src/run/convert.rs index 76c48c013..4f93e2297 100644 --- a/forward_system/src/run/convert.rs +++ b/forward_system/src/run/convert.rs @@ -123,7 +123,6 @@ impl IntoInterface basic_bootloader::bootloader::errors::InvalidTransaction::InvalidChainId => { InvalidTransaction::InvalidChainId } basic_bootloader::bootloader::errors::InvalidTransaction::AccessListNotSupported => { InvalidTransaction::AccessListNotSupported } basic_bootloader::bootloader::errors::InvalidTransaction::PubdataPriceTooHigh => { InvalidTransaction::PubdataPriceTooHigh } - basic_bootloader::bootloader::errors::InvalidTransaction::BlockGasLimitTooHigh => { InvalidTransaction::BlockGasLimitTooHigh } basic_bootloader::bootloader::errors::InvalidTransaction::UpgradeTxNotFirst => { InvalidTransaction::UpgradeTxNotFirst } basic_bootloader::bootloader::errors::InvalidTransaction::ReceivedInsufficientFees { received, required } => { InvalidTransaction::ReceivedInsufficientFees { received, required } } basic_bootloader::bootloader::errors::InvalidTransaction::InvalidMagic => { InvalidTransaction::InvalidMagic } diff --git a/proof_running_system/Cargo.toml b/proof_running_system/Cargo.toml index 9c36fb4bb..d7e9e30d4 100644 --- a/proof_running_system/Cargo.toml +++ b/proof_running_system/Cargo.toml @@ -35,8 +35,7 @@ proving = ["crypto/proving", "basic_system/proving", "delegation"] delegation = ["u256/delegation", "zk_ee/delegation", "evm_interpreter/delegation", "basic_system/delegation", "system_hooks/delegation", "basic_bootloader/delegation"] scalloc = [] cycle_marker = ["zk_ee/cycle_marker", "evm_interpreter/cycle_marker", "basic_system/cycle_marker", "basic_bootloader/cycle_marker"] -unlimited_native = ["basic_bootloader/unlimited_native"] -benchmarking = ["cycle_marker", "unlimited_native"] +benchmarking = ["cycle_marker"] global-alloc = ["zk_ee/global-alloc"] error_origins = ["zk_ee/error_origins"] multiblock-batch = [] @@ -52,8 +51,8 @@ production = ["basic_bootloader/eip-7702", "system_hooks/p256_precompile"] # cannot be proved (the transpiler replayer rejects them by design). for_tests = ["production", "state-diffs-pi", "basic_bootloader/eip-4844"] -# Features used for eth_runner -eth_runner = ["basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "state-diffs-pi", "unlimited_native", "basic_bootloader/burn_base_fee", "basic_bootloader/eip-4844"] +# Features used for eth_runner. +eth_runner = ["basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "state-diffs-pi", "basic_bootloader/burn_base_fee", "basic_bootloader/eip-4844"] # Additional features used for eth_stf in eth_runner eth_stf = ["basic_bootloader/eip-7702","basic_bootloader/eip-7623", "system_hooks/bls12_381", "system_hooks/blake2f", "evm_interpreter/bls12_381", "evm_interpreter/blake2f"] @@ -68,7 +67,7 @@ fusaka = ["pectra", "basic_bootloader/fusaka", "evm_interpreter/clz"] fusaka-blobs = ["basic_bootloader/fusaka-blobs"] # Features used for evm_tester -evm_tester = ["basic_bootloader/resources_for_tester", "basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "state-diffs-pi", "basic_bootloader/eip-7702", "system_hooks/p256_precompile", "basic_bootloader/burn_base_fee", "system_hooks/mock-unsupported-precompiles", "unlimited_native", "basic_bootloader/eip-4844"] +evm_tester = ["basic_bootloader/disable_system_contracts", "zk_ee/prevrandao", "state-diffs-pi", "basic_bootloader/eip-7702", "system_hooks/p256_precompile", "basic_bootloader/burn_base_fee", "system_hooks/mock-unsupported-precompiles", "basic_bootloader/eip-4844"] # Features used for evm_tester with Pectra hardfork evm_tester_pectra = ["evm_tester", "pectra"] diff --git a/tests/evm_divergence_validator/Cargo.toml b/tests/evm_divergence_validator/Cargo.toml index 6db97f90a..753fa9408 100644 --- a/tests/evm_divergence_validator/Cargo.toml +++ b/tests/evm_divergence_validator/Cargo.toml @@ -32,7 +32,7 @@ log = { workspace = true } hex = { workspace = true } tempfile = "3" -rig = { path = "../rig", features = ["no_print", "unlimited_native"] } +rig = { path = "../rig", features = ["no_print"] } zksync_os_tests_common = { path = "../common" } zksync_os_revm_runner = { path = "../revm_runner" } zk_ee = { path = "../../zk_ee" } diff --git a/tests/evm_divergence_validator/README.md b/tests/evm_divergence_validator/README.md index 7b349abdc..6a4d87965 100644 --- a/tests/evm_divergence_validator/README.md +++ b/tests/evm_divergence_validator/README.md @@ -193,5 +193,5 @@ The tool uses the existing REVM consistency checker from `tests/revm_runner/`, w ## Design notes - All steps run in a single block. Multi-block scenarios are not yet supported. -- The tool enables `unlimited_native` and `independent_gas`, so ZKsync OS gas accounting follows standard EVM rules and is not overridden from ZKsync OS to REVM. The validator reports `gas_used` per step, but does not treat per-transaction gas differences as a separate divergence check — gas differences surface through balance diffs in the state comparison. +- The tool enables unlimited native(`native_price` == 0) and `independent_gas`, so ZKsync OS gas accounting follows standard EVM rules and is not overridden from ZKsync OS to REVM. The validator reports `gas_used` per step, but does not treat per-transaction gas differences as a separate divergence check — gas differences surface through balance diffs in the state comparison. - The REVM side uses `zksync-os-revm` (adapted REVM), which accounts for ZKsync-specific behaviors (precompile differences, fee distribution, etc.). This is intentional — divergences caught here are real bugs, not known differences. diff --git a/tests/evm_divergence_validator/src/runner.rs b/tests/evm_divergence_validator/src/runner.rs index 55af9ac4a..ef0b3ecba 100644 --- a/tests/evm_divergence_validator/src/runner.rs +++ b/tests/evm_divergence_validator/src/runner.rs @@ -485,7 +485,7 @@ fn parse_alloy_u256(s: &str) -> anyhow::Result { fn make_block_context(block: &BlockDef) -> rig::BlockContext { rig::BlockContext { eip1559_basefee: ruint::aliases::U256::from(block.basefee.unwrap_or(DEFAULT_MAX_FEE)), - native_price: ruint::aliases::U256::from(10u64), + native_price: ruint::aliases::U256::from(0u64), // native resources will be unlimited pubdata_price: Default::default(), timestamp: block.timestamp.unwrap_or(1_700_000_000), gas_limit: block.gas_limit.unwrap_or(30_000_000), diff --git a/tests/evm_tester/src/vm/zk_ee/mod.rs b/tests/evm_tester/src/vm/zk_ee/mod.rs index 618c81995..9b9fae72e 100644 --- a/tests/evm_tester/src/vm/zk_ee/mod.rs +++ b/tests/evm_tester/src/vm/zk_ee/mod.rs @@ -92,7 +92,7 @@ impl ZKsyncOS { let context = BlockContext { eip1559_basefee: ruint::Uint::from_str(&system_context.base_fee.to_string()) .expect("Invalid basefee"), - native_price: ruint::aliases::U256::from(1), + native_price: ruint::aliases::U256::from(0), // native resources will be unlimited pubdata_price: Default::default(), timestamp: system_context.block_timestamp as u64, gas_limit, diff --git a/tests/fuzzer/fuzz/wrappers/basic_bootloader_forward/Cargo.toml b/tests/fuzzer/fuzz/wrappers/basic_bootloader_forward/Cargo.toml index cd683c644..f97893a9b 100644 --- a/tests/fuzzer/fuzz/wrappers/basic_bootloader_forward/Cargo.toml +++ b/tests/fuzzer/fuzz/wrappers/basic_bootloader_forward/Cargo.toml @@ -34,7 +34,5 @@ eip-7623 = [] eip-4844 = ["system_hooks/point_eval_precompile"] burn_base_fee = [] cycle_marker = ["system_hooks/cycle_marker", "cycle_marker/log_to_file"] -resources_for_tester = [] -unlimited_native = [] disable_system_contracts = [] error_origins = ["zk_ee/error_origins"] diff --git a/tests/instances/eth_runner/README.md b/tests/instances/eth_runner/README.md index 8c3147bf0..dd938d70e 100644 --- a/tests/instances/eth_runner/README.md +++ b/tests/instances/eth_runner/README.md @@ -24,7 +24,7 @@ The tool has two modes: `single-run` and `live-run`. The former takes as argumen From the root of the project, run: ```raw -RUST_LOG=eth_runner=info cargo run -p eth_runner --release --features rig/no_print,rig/unlimited_native -- single-run --block-dir tests/instances/eth_runner/blocks/22244135 --randomized +RUST_LOG=eth_runner=info cargo run -p eth_runner --release --features rig/no_print -- single-run --block-dir tests/instances/eth_runner/blocks/22244135 --randomized ``` This will run the example block committed to the repo (22244135). Some more example blocks can be found in https://github.com/antoniolocascio/ethereum-block-examples. @@ -34,7 +34,7 @@ This will run the example block committed to the repo (22244135). Some more exam From the root of the projects, run: ```raw -RUST_LOG=eth_runner=info cargo run -p eth_runner --release --features rig/no_print,rig/unlimited_native -- live-run --start-block 19299000 --end-block 19299005 --endpoint ENDPOINT --db ../db +RUST_LOG=eth_runner=info cargo run -p eth_runner --release --features rig/no_print -- live-run --start-block 19299000 --end-block 19299005 --endpoint ENDPOINT --db ../db ``` This command will fetch blocks in the range [19299000, 19299005] from the Ethereum archive node `ENDPOINT`. It creates a local database to cache some RPC information. diff --git a/tests/instances/eth_runner/scripts/run_parallel_processes.sh b/tests/instances/eth_runner/scripts/run_parallel_processes.sh index 299fc1572..316f074ce 100755 --- a/tests/instances/eth_runner/scripts/run_parallel_processes.sh +++ b/tests/instances/eth_runner/scripts/run_parallel_processes.sh @@ -88,7 +88,7 @@ for i in $(seq 1 $NUM_PROCESSES); do CMD="$CMD REFETCH_TRACES=$REFETCH_TRACES" fi - CMD="$CMD cargo run --manifest-path tests/instances/eth_runner/Cargo.toml --release --features rig/no_print,rig/unlimited_native -- \ + CMD="$CMD cargo run --manifest-path tests/instances/eth_runner/Cargo.toml --release --features rig/no_print -- \ live-run \ --start-block $CURRENT_START \ --end-block $CURRENT_END \ diff --git a/tests/instances/eth_runner/src/block.rs b/tests/instances/eth_runner/src/block.rs index f70e9aa8d..4abcefe8e 100644 --- a/tests/instances/eth_runner/src/block.rs +++ b/tests/instances/eth_runner/src/block.rs @@ -61,7 +61,7 @@ impl Block { timestamp: self.result.header.timestamp, eip1559_basefee: base_fee, pubdata_price: U256::ZERO, - native_price: (base_fee / U256::from(100)).max(U256::ONE), + native_price: U256::ZERO, coinbase: B160::from_alloy(self.result.header.beneficiary), gas_limit: self.result.header.gas_limit, pubdata_limit: u64::MAX, diff --git a/tests/instances/precompiles/src/lib.rs b/tests/instances/precompiles/src/lib.rs index ab412300d..cdd89637c 100644 --- a/tests/instances/precompiles/src/lib.rs +++ b/tests/instances/precompiles/src/lib.rs @@ -103,9 +103,9 @@ fn run_precompile_inner( wallet.clone(), ); - // We use a very high native per gas ratio + // Unlimited native (native price == 0) let block_context = BlockContext { - native_price: U256::ONE, + native_price: U256::ZERO, eip1559_basefee: U256::from(25_000), ..Default::default() }; @@ -6616,9 +6616,9 @@ fn test_regression_p256_is_warm() { wallet.clone(), ); - // We use a very high native per gas ratio + // Unlimited native (native price == 0) let block_context = BlockContext { - native_price: U256::ONE, + native_price: U256::ZERO, eip1559_basefee: U256::from(25_000), ..Default::default() }; diff --git a/tests/revm_runner/src/revm_runner.rs b/tests/revm_runner/src/revm_runner.rs index bbff848f1..fce6548ce 100644 --- a/tests/revm_runner/src/revm_runner.rs +++ b/tests/revm_runner/src/revm_runner.rs @@ -61,7 +61,8 @@ where spec: ZkSpecId, /// When true, REVM computes gas independently instead of using /// ZKsync OS's `gas_used` as an override. Best combined with - /// `unlimited_native` so that gas models are equivalent. + /// `native_price = 0` in the block metadata so that the ZKsync OS + /// native-correction is disabled and gas models are equivalent. independent_gas: bool, } diff --git a/tests/rig/Cargo.toml b/tests/rig/Cargo.toml index 94f4ac63b..203a3771e 100644 --- a/tests/rig/Cargo.toml +++ b/tests/rig/Cargo.toml @@ -43,7 +43,6 @@ testing = [] e2e_proving = ["airbender-host"] no_print = ["forward_system/no_print"] cycle_marker = ["dep:cycle_marker", "zksync_os_runner/cycle_marker", "zk_ee/cycle_marker", "evm_interpreter/cycle_marker", "basic_system/cycle_marker", "basic_bootloader/cycle_marker"] -unlimited_native = ["forward_system/unlimited_native"] production = ["forward_system/production"] # Features for test instances for_tests = ["forward_system/for_tests", "callable_oracles/testing"] @@ -57,6 +56,3 @@ evm_tester_pectra = ["forward_system/evm_tester_pectra"] fusaka = ["forward_system/fusaka"] fusaka-blobs = ["forward_system/fusaka-blobs"] evm_tester_fusaka = ["forward_system/evm_tester_fusaka"] -# Features used for legacy evm_tester. Only defined in forward system, -# as the legacy evm_tester does not perform a proof run. -evm_tester_legacy = ["forward_system/evm_tester_legacy"] diff --git a/tests/rig/src/chain.rs b/tests/rig/src/chain.rs index 722f97094..5ab22b34e 100644 --- a/tests/rig/src/chain.rs +++ b/tests/rig/src/chain.rs @@ -224,7 +224,8 @@ pub struct RunConfig { // Can be enabled via ZKSYNC_REVM_CONSISTENCY_CHECK env var. pub check_revm_consistency: bool, /// When true, REVM computes gas independently instead of using - /// ZKsync OS's `gas_used` override. Best combined with `unlimited_native`. + /// ZKsync OS's `gas_used` override. Best combined with `native_price = 0` + /// in the block metadata. pub revm_independent_gas: bool, pub update_state_after_block_execution: bool, }