From de4d729dbd1f2f1bf524be75a0f8ee9d9cd372f8 Mon Sep 17 00:00:00 2001 From: perekopskiy <53865202+perekopskiy@users.noreply.github.com> Date: Fri, 16 Feb 2024 17:07:11 +0200 Subject: [PATCH] fix(state-keeper): Add GasForBatchTip criterion (#1096) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What ❔ - add GasForBatchTip criterion instead of checking gas in batch executor - removes the assumption that a single tx can't consume whole batch gas (with or without batch tip) ## Why ❔ That check in batch executor ``` if !vm.has_enough_gas_for_batch_tip() { return TxExecutionResult::BootloaderOutOfGasForBlockTip; } ``` conceptually was a criterion and should be extracted to a separate seal criteria. This way EN doesn't perform this check which is a correct behavior and code is cleaner. ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [x] Tests for the changes have been added / updated. - [x] Documentation comments have been added / updated. - [x] Code has been formatted via `zk fmt` and `zk lint`. - [x] Spellcheck has been run via `zk spellcheck`. - [x] Linkcheck has been run via `zk linkcheck`. --- .../src/glue/types/vm/vm_block_result.rs | 6 ++ .../types/vm/vm_partial_execution_result.rs | 12 ++- core/lib/multivm/src/interface/traits/vm.rs | 4 +- .../src/interface/types/outputs/statistic.rs | 2 + core/lib/multivm/src/utils.rs | 19 ++++ core/lib/multivm/src/versions/vm_1_3_2/vm.rs | 6 +- .../src/versions/vm_1_3_2/vm_instance.rs | 10 +- .../implementation/execution.rs | 2 +- .../implementation/gas.rs | 13 +-- .../implementation/statistics.rs | 1 + .../src/versions/vm_boojum_integration/vm.rs | 5 +- .../vm_latest/implementation/execution.rs | 2 +- .../versions/vm_latest/implementation/gas.rs | 13 +-- .../vm_latest/implementation/statistics.rs | 1 + core/lib/multivm/src/versions/vm_latest/vm.rs | 5 +- core/lib/multivm/src/versions/vm_m5/vm.rs | 6 +- .../multivm/src/versions/vm_m5/vm_instance.rs | 7 +- core/lib/multivm/src/versions/vm_m6/vm.rs | 6 +- .../multivm/src/versions/vm_m6/vm_instance.rs | 10 +- .../implementation/execution.rs | 2 +- .../implementation/gas.rs | 13 +-- .../implementation/statistics.rs | 1 + .../src/versions/vm_refunds_enhancement/vm.rs | 6 +- .../implementation/execution.rs | 2 +- .../vm_virtual_blocks/implementation/gas.rs | 13 +-- .../implementation/statistics.rs | 1 + .../src/versions/vm_virtual_blocks/vm.rs | 6 +- core/lib/multivm/src/vm_instance.rs | 4 +- core/lib/types/src/fee.rs | 28 +++++- .../execution_sandbox/vm_metrics.rs | 1 + .../batch_executor/main_executor.rs | 6 +- .../src/state_keeper/batch_executor/mod.rs | 1 + .../zksync_core/src/state_keeper/keeper.rs | 58 +++++++---- .../seal_criteria/conditional_sealer.rs | 1 + .../criteria/gas_for_batch_tip.rs | 99 +++++++++++++++++++ .../seal_criteria/criteria/mod.rs | 7 +- .../src/state_keeper/seal_criteria/mod.rs | 2 + .../zksync_core/src/state_keeper/tests/mod.rs | 1 + .../src/state_keeper/tests/tester.rs | 2 + 39 files changed, 263 insertions(+), 121 deletions(-) create mode 100644 core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/gas_for_batch_tip.rs diff --git a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs index 9867c0c95b9..824b36a8297 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_block_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_block_result.rs @@ -43,6 +43,7 @@ impl GlueFrom for crate::interface::Fi total_log_queries: value.block_tip_result.logs.total_log_queries_count, computational_gas_used: value.full_result.gas_used, gas_used: value.full_result.gas_used, + gas_remaining: value.full_result.gas_remaining, pubdata_published: 0, circuit_statistic: Default::default(), }, @@ -104,6 +105,7 @@ impl GlueFrom for crate::interface::Fi total_log_queries: value.block_tip_result.logs.total_log_queries_count, computational_gas_used: value.full_result.computational_gas_used, gas_used: value.full_result.gas_used, + gas_remaining: value.full_result.gas_remaining, pubdata_published: 0, circuit_statistic: Default::default(), }, @@ -163,6 +165,7 @@ impl GlueFrom for crate::interface: total_log_queries: value.block_tip_result.logs.total_log_queries_count, computational_gas_used: value.full_result.computational_gas_used, gas_used: value.full_result.gas_used, + gas_remaining: value.full_result.gas_remaining, pubdata_published: 0, circuit_statistic: Default::default(), }, @@ -236,6 +239,7 @@ impl GlueFrom total_log_queries: value.full_result.total_log_queries, computational_gas_used: value.full_result.computational_gas_used, gas_used: value.full_result.gas_used, + gas_remaining: value.full_result.gas_remaining, pubdata_published: 0, circuit_statistic: Default::default(), }, @@ -267,6 +271,7 @@ impl GlueFrom total_log_queries: value.full_result.total_log_queries, computational_gas_used: 0, gas_used: value.full_result.gas_used, + gas_remaining: value.full_result.gas_remaining, pubdata_published: 0, circuit_statistic: Default::default(), }, @@ -314,6 +319,7 @@ impl GlueFrom total_log_queries: value.full_result.total_log_queries, computational_gas_used: value.full_result.computational_gas_used, gas_used: value.full_result.gas_used, + gas_remaining: value.full_result.gas_remaining, pubdata_published: 0, circuit_statistic: Default::default(), }, diff --git a/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs b/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs index 932b7616521..320917d3f4f 100644 --- a/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs +++ b/core/lib/multivm/src/glue/types/vm/vm_partial_execution_result.rs @@ -11,9 +11,9 @@ impl GlueFrom contracts_used: value.contracts_used, cycles_used: value.cycles_used, total_log_queries: value.logs.total_log_queries_count, - // There are no such fields in `m5` + // There are no such fields in `m5`. gas_used: 0, - // There are no such fields in `m5` + gas_remaining: 0, computational_gas_used: 0, pubdata_published: 0, circuit_statistic: Default::default(), @@ -36,9 +36,11 @@ impl GlueFrom statistics: crate::interface::VmExecutionStatistics { contracts_used: value.contracts_used, cycles_used: value.cycles_used, - gas_used: value.computational_gas_used, computational_gas_used: value.computational_gas_used, total_log_queries: value.logs.total_log_queries_count, + // There are no such fields in `m6`. + gas_used: 0, + gas_remaining: 0, pubdata_published: 0, circuit_statistic: Default::default(), }, @@ -60,9 +62,11 @@ impl GlueFrom statistics: crate::interface::VmExecutionStatistics { contracts_used: value.contracts_used, cycles_used: value.cycles_used, - gas_used: value.computational_gas_used, computational_gas_used: value.computational_gas_used, total_log_queries: value.logs.total_log_queries_count, + // There are no such fields in `1_3_2`. + gas_used: 0, + gas_remaining: 0, pubdata_published: 0, circuit_statistic: Default::default(), }, diff --git a/core/lib/multivm/src/interface/traits/vm.rs b/core/lib/multivm/src/interface/traits/vm.rs index dd31c00e98f..4d3417cdeb6 100644 --- a/core/lib/multivm/src/interface/traits/vm.rs +++ b/core/lib/multivm/src/interface/traits/vm.rs @@ -129,8 +129,8 @@ pub trait VmInterface { /// Record VM memory metrics. fn record_vm_memory_metrics(&self) -> VmMemoryMetrics; - /// Whether the VM still has enough gas to execute the batch tip - fn has_enough_gas_for_batch_tip(&self) -> bool; + /// How much gas is left in the current stack frame. + fn gas_remaining(&self) -> u32; /// Execute batch till the end and return the result, with final execution state /// and bootloader memory. diff --git a/core/lib/multivm/src/interface/types/outputs/statistic.rs b/core/lib/multivm/src/interface/types/outputs/statistic.rs index 88c45166b55..f61954885fd 100644 --- a/core/lib/multivm/src/interface/types/outputs/statistic.rs +++ b/core/lib/multivm/src/interface/types/outputs/statistic.rs @@ -9,6 +9,8 @@ pub struct VmExecutionStatistics { pub cycles_used: u32, /// Gas used by the VM during the tx execution. pub gas_used: u32, + /// Gas remaining after the tx execution. + pub gas_remaining: u32, /// Computational gas used by the VM during the tx execution. pub computational_gas_used: u32, /// Number of log queries produced by the VM during the tx execution. diff --git a/core/lib/multivm/src/utils.rs b/core/lib/multivm/src/utils.rs index 459739c45ba..1488ee3df19 100644 --- a/core/lib/multivm/src/utils.rs +++ b/core/lib/multivm/src/utils.rs @@ -184,6 +184,25 @@ pub fn get_bootloader_max_txs_in_batch(version: VmVersion) -> usize { } } +pub fn gas_bootloader_batch_tip_overhead(version: VmVersion) -> u32 { + match version { + VmVersion::M5WithRefunds + | VmVersion::M5WithoutRefunds + | VmVersion::M6Initial + | VmVersion::M6BugWithCompressionFixed + | VmVersion::Vm1_3_2 + | VmVersion::VmVirtualBlocks + | VmVersion::VmVirtualBlocksRefundsEnhancement => { + // For these versions the overhead has not been calculated and it has not been used with those versions. + 0 + } + VmVersion::VmBoojumIntegration => { + crate::vm_boojum_integration::constants::BOOTLOADER_BATCH_TIP_OVERHEAD + } + VmVersion::Vm1_4_1 => crate::vm_latest::constants::BOOTLOADER_BATCH_TIP_OVERHEAD, + } +} + pub fn get_max_gas_per_pubdata_byte(version: VmVersion) -> u64 { match version { VmVersion::M5WithRefunds | VmVersion::M5WithoutRefunds => { diff --git a/core/lib/multivm/src/versions/vm_1_3_2/vm.rs b/core/lib/multivm/src/versions/vm_1_3_2/vm.rs index ea5647c5636..03fae330685 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/vm.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/vm.rs @@ -284,10 +284,8 @@ impl VmInterface for Vm { } } - fn has_enough_gas_for_batch_tip(&self) -> bool { - // For this version this overhead has not been calculated and it has not been used with those versions. - // We return some value just in case for backwards compatibility - true + fn gas_remaining(&self) -> u32 { + self.vm.gas_remaining() } fn finish_batch(&mut self) -> FinishedL1Batch { diff --git a/core/lib/multivm/src/versions/vm_1_3_2/vm_instance.rs b/core/lib/multivm/src/versions/vm_1_3_2/vm_instance.rs index fabdf541b71..bbc512030f4 100644 --- a/core/lib/multivm/src/versions/vm_1_3_2/vm_instance.rs +++ b/core/lib/multivm/src/versions/vm_1_3_2/vm_instance.rs @@ -111,6 +111,7 @@ pub struct VmExecutionResult { /// is executed, but it's not enforced. So best we can do is to calculate the amount of gas before and /// after the invocation, leaving the interpretation of this value to the user. pub gas_used: u32, + pub gas_remaining: u32, /// This value also depends on the context, the same as `gas_used`. pub computational_gas_used: u32, pub contracts_used: usize, @@ -211,9 +212,8 @@ fn vm_may_have_ended( ) -> Option { let basic_execution_result = vm_may_have_ended_inner(&vm.state)?; - let gas_used = gas_before - .checked_sub(vm.gas_remaining()) - .expect("underflow"); + let gas_remaining = vm.gas_remaining(); + let gas_used = gas_before.checked_sub(gas_remaining).expect("underflow"); match basic_execution_result { NewVmExecutionResult::Ok(data) => { @@ -226,6 +226,7 @@ fn vm_may_have_ended( l2_to_l1_logs: vec![], return_data: data, gas_used, + gas_remaining, // The correct `computational_gas_used` value for this field should be set separately later. computational_gas_used: 0, contracts_used: vm @@ -266,6 +267,7 @@ fn vm_may_have_ended( l2_to_l1_logs: vec![], return_data: vec![], gas_used, + gas_remaining, // The correct `computational_gas_used` value for this field should be set separately later. computational_gas_used: 0, contracts_used: vm @@ -289,6 +291,7 @@ fn vm_may_have_ended( l2_to_l1_logs: vec![], return_data: vec![], gas_used, + gas_remaining, // The correct `computational_gas_used` value for this field should be set separately later. computational_gas_used: 0, contracts_used: vm @@ -792,6 +795,7 @@ impl VmInstance { l2_to_l1_logs: vec![], return_data: vec![], gas_used: 0, + gas_remaining: 0, computational_gas_used: 0, contracts_used: 0, revert_reason: Some(VmRevertReasonParsingResult { diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs index 0f608c83333..22f2a50efde 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/execution.rs @@ -4,7 +4,7 @@ use zksync_state::WriteStorage; use crate::{ interface::{ types::tracer::{TracerExecutionStatus, VmExecutionStopReason}, - VmExecutionMode, VmExecutionResultAndLogs, + VmExecutionMode, VmExecutionResultAndLogs, VmInterface, }, vm_boojum_integration::{ old_vm::utils::{vm_may_have_ended_inner, VmExecutionResult}, diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/gas.rs b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/gas.rs index 56f13de05e5..304b7a3b756 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/gas.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/gas.rs @@ -1,23 +1,12 @@ use zksync_state::WriteStorage; use crate::{ + interface::VmInterface, vm_boojum_integration::{tracers::DefaultExecutionTracer, vm::Vm}, HistoryMode, }; impl Vm { - /// Returns the amount of gas remaining to the VM. - /// Note that this *does not* correspond to the gas limit of a transaction. - /// To calculate the amount of gas spent by transaction, you should call this method before and after - /// the execution, and subtract these values. - /// - /// Note: this method should only be called when either transaction is fully completed or VM completed - /// its execution. Remaining gas value is read from the current stack frame, so if you'll attempt to - /// read it during the transaction execution, you may receive invalid value. - pub(crate) fn gas_remaining(&self) -> u32 { - self.state.local_state.callstack.current.ergs_remaining - } - pub(crate) fn calculate_computational_gas_used( &self, tracer: &DefaultExecutionTracer, diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/statistics.rs b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/statistics.rs index 2bb0f1dc0f7..10972b5408b 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/implementation/statistics.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/implementation/statistics.rs @@ -38,6 +38,7 @@ impl Vm { .get_decommitted_bytecodes_after_timestamp(timestamp_initial), cycles_used: self.state.local_state.monotonic_cycle_counter - cycles_initial, gas_used: gas_remaining_before - gas_remaining_after, + gas_remaining: gas_remaining_after, computational_gas_used, total_log_queries: total_log_queries_count, pubdata_published, diff --git a/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs b/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs index 9e897ac3070..5f6c5a060e8 100644 --- a/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs +++ b/core/lib/multivm/src/versions/vm_boojum_integration/vm.rs @@ -7,7 +7,6 @@ use zksync_types::{ }; use zksync_utils::bytecode::CompressedBytecodeInfo; -use super::constants::BOOTLOADER_BATCH_TIP_OVERHEAD; use crate::{ glue::GlueInto, interface::{ @@ -165,8 +164,8 @@ impl VmInterface for Vm { self.record_vm_memory_metrics_inner() } - fn has_enough_gas_for_batch_tip(&self) -> bool { - self.state.local_state.callstack.current.ergs_remaining >= BOOTLOADER_BATCH_TIP_OVERHEAD + fn gas_remaining(&self) -> u32 { + self.state.local_state.callstack.current.ergs_remaining } fn finish_batch(&mut self) -> FinishedL1Batch { diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs index 21e5b16cd2d..0c836f64097 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/execution.rs @@ -4,7 +4,7 @@ use zksync_state::WriteStorage; use crate::{ interface::{ types::tracer::{TracerExecutionStatus, VmExecutionStopReason}, - VmExecutionMode, VmExecutionResultAndLogs, + VmExecutionMode, VmExecutionResultAndLogs, VmInterface, }, vm_latest::{ old_vm::utils::{vm_may_have_ended_inner, VmExecutionResult}, diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/gas.rs b/core/lib/multivm/src/versions/vm_latest/implementation/gas.rs index 8b21e7aeca1..13932dd3c38 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/gas.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/gas.rs @@ -1,23 +1,12 @@ use zksync_state::WriteStorage; use crate::{ + interface::VmInterface, vm_latest::{tracers::DefaultExecutionTracer, vm::Vm}, HistoryMode, }; impl Vm { - /// Returns the amount of gas remaining to the VM. - /// Note that this *does not* correspond to the gas limit of a transaction. - /// To calculate the amount of gas spent by transaction, you should call this method before and after - /// the execution, and subtract these values. - /// - /// Note: this method should only be called when either transaction is fully completed or VM completed - /// its execution. Remaining gas value is read from the current stack frame, so if you'll attempt to - /// read it during the transaction execution, you may receive invalid value. - pub(crate) fn gas_remaining(&self) -> u32 { - self.state.local_state.callstack.current.ergs_remaining - } - pub(crate) fn calculate_computational_gas_used( &self, tracer: &DefaultExecutionTracer, diff --git a/core/lib/multivm/src/versions/vm_latest/implementation/statistics.rs b/core/lib/multivm/src/versions/vm_latest/implementation/statistics.rs index 0349b7d8cda..3e969d951b5 100644 --- a/core/lib/multivm/src/versions/vm_latest/implementation/statistics.rs +++ b/core/lib/multivm/src/versions/vm_latest/implementation/statistics.rs @@ -38,6 +38,7 @@ impl Vm { .get_decommitted_bytecodes_after_timestamp(timestamp_initial), cycles_used: self.state.local_state.monotonic_cycle_counter - cycles_initial, gas_used: gas_remaining_before - gas_remaining_after, + gas_remaining: gas_remaining_after, computational_gas_used, total_log_queries: total_log_queries_count, pubdata_published, diff --git a/core/lib/multivm/src/versions/vm_latest/vm.rs b/core/lib/multivm/src/versions/vm_latest/vm.rs index 4fa8c58a0e1..f570bdac72e 100644 --- a/core/lib/multivm/src/versions/vm_latest/vm.rs +++ b/core/lib/multivm/src/versions/vm_latest/vm.rs @@ -7,7 +7,6 @@ use zksync_types::{ }; use zksync_utils::bytecode::CompressedBytecodeInfo; -use super::constants::BOOTLOADER_BATCH_TIP_OVERHEAD; use crate::{ glue::GlueInto, interface::{ @@ -165,8 +164,8 @@ impl VmInterface for Vm { self.record_vm_memory_metrics_inner() } - fn has_enough_gas_for_batch_tip(&self) -> bool { - self.state.local_state.callstack.current.ergs_remaining >= BOOTLOADER_BATCH_TIP_OVERHEAD + fn gas_remaining(&self) -> u32 { + self.state.local_state.callstack.current.ergs_remaining } fn finish_batch(&mut self) -> FinishedL1Batch { diff --git a/core/lib/multivm/src/versions/vm_m5/vm.rs b/core/lib/multivm/src/versions/vm_m5/vm.rs index 472f0688248..6493ea6defc 100644 --- a/core/lib/multivm/src/versions/vm_m5/vm.rs +++ b/core/lib/multivm/src/versions/vm_m5/vm.rs @@ -224,10 +224,8 @@ impl VmInterface for Vm { } } - fn has_enough_gas_for_batch_tip(&self) -> bool { - // For this version this overhead has not been calculated and it has not been used with those versions. - // We return some value just in case for backwards compatibility - true + fn gas_remaining(&self) -> u32 { + self.vm.gas_remaining() } fn finish_batch(&mut self) -> FinishedL1Batch { diff --git a/core/lib/multivm/src/versions/vm_m5/vm_instance.rs b/core/lib/multivm/src/versions/vm_m5/vm_instance.rs index ed7d8078e19..085c219f43c 100644 --- a/core/lib/multivm/src/versions/vm_m5/vm_instance.rs +++ b/core/lib/multivm/src/versions/vm_m5/vm_instance.rs @@ -128,6 +128,7 @@ pub struct VmExecutionResult { /// is executed, but it's not enforced. So best we can do is to calculate the amount of gas before and /// after the invocation, leaving the interpretation of this value to the user. pub gas_used: u32, + pub gas_remaining: u32, pub contracts_used: usize, pub revert_reason: Option, pub trace: VmExecutionTrace, @@ -228,7 +229,8 @@ fn vm_may_have_ended_inner( fn vm_may_have_ended(vm: &VmInstance, gas_before: u32) -> Option { let basic_execution_result = vm_may_have_ended_inner(&vm.state)?; - let gas_used = gas_before - vm.gas_remaining(); + let gas_remaining = vm.gas_remaining(); + let gas_used = gas_before - gas_remaining; match basic_execution_result { NewVmExecutionResult::Ok(data) => { @@ -241,6 +243,7 @@ fn vm_may_have_ended(vm: &VmInstance, gas_before: u32) -> Option< l2_to_l1_logs: vec![], return_data: data, gas_used, + gas_remaining, contracts_used: vm .state .decommittment_processor @@ -279,6 +282,7 @@ fn vm_may_have_ended(vm: &VmInstance, gas_before: u32) -> Option< l2_to_l1_logs: vec![], return_data: vec![], gas_used, + gas_remaining, contracts_used: vm .state .decommittment_processor @@ -300,6 +304,7 @@ fn vm_may_have_ended(vm: &VmInstance, gas_before: u32) -> Option< l2_to_l1_logs: vec![], return_data: vec![], gas_used, + gas_remaining, contracts_used: vm .state .decommittment_processor diff --git a/core/lib/multivm/src/versions/vm_m6/vm.rs b/core/lib/multivm/src/versions/vm_m6/vm.rs index 698041d6cb2..d85c80fee4b 100644 --- a/core/lib/multivm/src/versions/vm_m6/vm.rs +++ b/core/lib/multivm/src/versions/vm_m6/vm.rs @@ -314,10 +314,8 @@ impl VmInterface for Vm { } } - fn has_enough_gas_for_batch_tip(&self) -> bool { - // For this version this overhead has not been calculated and it has not been used with those versions. - // We return some value just in case for backwards compatibility - true + fn gas_remaining(&self) -> u32 { + self.vm.gas_remaining() } fn finish_batch(&mut self) -> FinishedL1Batch { diff --git a/core/lib/multivm/src/versions/vm_m6/vm_instance.rs b/core/lib/multivm/src/versions/vm_m6/vm_instance.rs index 68416970ee8..9f5e25fb2f4 100644 --- a/core/lib/multivm/src/versions/vm_m6/vm_instance.rs +++ b/core/lib/multivm/src/versions/vm_m6/vm_instance.rs @@ -127,6 +127,7 @@ pub struct VmExecutionResult { /// is executed, but it's not enforced. So best we can do is to calculate the amount of gas before and /// after the invocation, leaving the interpretation of this value to the user. pub gas_used: u32, + pub gas_remaining: u32, /// This value also depends on the context, the same as `gas_used`. pub computational_gas_used: u32, pub contracts_used: usize, @@ -227,9 +228,8 @@ fn vm_may_have_ended( ) -> Option { let basic_execution_result = vm_may_have_ended_inner(&vm.state)?; - let gas_used = gas_before - .checked_sub(vm.gas_remaining()) - .expect("underflow"); + let gas_remaining = vm.gas_remaining(); + let gas_used = gas_before.checked_sub(gas_remaining).expect("underflow"); match basic_execution_result { NewVmExecutionResult::Ok(data) => { @@ -242,6 +242,7 @@ fn vm_may_have_ended( l2_to_l1_logs: vec![], return_data: data, gas_used, + gas_remaining, // The correct `computational_gas_used` value for this field should be set separately later. computational_gas_used: 0, contracts_used: vm @@ -282,6 +283,7 @@ fn vm_may_have_ended( l2_to_l1_logs: vec![], return_data: vec![], gas_used, + gas_remaining, // The correct `computational_gas_used` value for this field should be set separately later. computational_gas_used: 0, contracts_used: vm @@ -305,6 +307,7 @@ fn vm_may_have_ended( l2_to_l1_logs: vec![], return_data: vec![], gas_used, + gas_remaining, // The correct `computational_gas_used` value for this field should be set separately later. computational_gas_used: 0, contracts_used: vm @@ -805,6 +808,7 @@ impl VmInstance { l2_to_l1_logs: vec![], return_data: vec![], gas_used: 0, + gas_remaining: 0, computational_gas_used: 0, contracts_used: 0, revert_reason: Some(VmRevertReasonParsingResult { diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs index a1d81bdce5e..f1de2afd8b7 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/execution.rs @@ -4,7 +4,7 @@ use zksync_state::WriteStorage; use crate::{ interface::{ tracer::{TracerExecutionStatus, VmExecutionStopReason}, - VmExecutionMode, VmExecutionResultAndLogs, + VmExecutionMode, VmExecutionResultAndLogs, VmInterface, }, vm_refunds_enhancement::{ old_vm::utils::{vm_may_have_ended_inner, VmExecutionResult}, diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/gas.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/gas.rs index 4083e27b0b3..bc5913fdf31 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/gas.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/gas.rs @@ -1,23 +1,12 @@ use zksync_state::WriteStorage; use crate::{ + interface::VmInterface, vm_refunds_enhancement::{tracers::DefaultExecutionTracer, vm::Vm}, HistoryMode, }; impl Vm { - /// Returns the amount of gas remaining to the VM. - /// Note that this *does not* correspond to the gas limit of a transaction. - /// To calculate the amount of gas spent by transaction, you should call this method before and after - /// the execution, and subtract these values. - /// - /// Note: this method should only be called when either transaction is fully completed or VM completed - /// its execution. Remaining gas value is read from the current stack frame, so if you'll attempt to - /// read it during the transaction execution, you may receive invalid value. - pub(crate) fn gas_remaining(&self) -> u32 { - self.state.local_state.callstack.current.ergs_remaining - } - pub(crate) fn calculate_computational_gas_used( &self, tracer: &DefaultExecutionTracer, diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/statistics.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/statistics.rs index 49d4b02de8b..c29843d7e4a 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/statistics.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/implementation/statistics.rs @@ -37,6 +37,7 @@ impl Vm { .get_decommitted_bytecodes_after_timestamp(timestamp_initial), cycles_used: self.state.local_state.monotonic_cycle_counter - cycles_initial, gas_used: gas_remaining_before - gas_remaining_after, + gas_remaining: gas_remaining_after, computational_gas_used, total_log_queries: total_log_queries_count, pubdata_published, diff --git a/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs b/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs index 2e4df854e5a..2d77adc3113 100644 --- a/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs +++ b/core/lib/multivm/src/versions/vm_refunds_enhancement/vm.rs @@ -151,10 +151,8 @@ impl VmInterface for Vm { } } - fn has_enough_gas_for_batch_tip(&self) -> bool { - // For this version this overhead has not been calculated and it has not been used with those versions. - // We return some value just in case for backwards compatibility - true + fn gas_remaining(&self) -> u32 { + self.state.local_state.callstack.current.ergs_remaining } fn record_vm_memory_metrics(&self) -> VmMemoryMetrics { diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs index 2938280d266..78a817f647c 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/execution.rs @@ -4,7 +4,7 @@ use zksync_state::WriteStorage; use crate::{ interface::{ tracer::{TracerExecutionStopReason, VmExecutionStopReason}, - VmExecutionMode, VmExecutionResultAndLogs, + VmExecutionMode, VmExecutionResultAndLogs, VmInterface, }, vm_virtual_blocks::{ old_vm::utils::{vm_may_have_ended_inner, VmExecutionResult}, diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/gas.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/gas.rs index 0ca52d2b687..ea8df4cd7e1 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/gas.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/gas.rs @@ -1,23 +1,12 @@ use zksync_state::WriteStorage; use crate::{ + interface::VmInterface, vm_virtual_blocks::{tracers::DefaultExecutionTracer, vm::Vm}, HistoryMode, }; impl Vm { - /// Returns the amount of gas remaining to the VM. - /// Note that this *does not* correspond to the gas limit of a transaction. - /// To calculate the amount of gas spent by transaction, you should call this method before and after - /// the execution, and subtract these values. - /// - /// Note: this method should only be called when either transaction is fully completed or VM completed - /// its execution. Remaining gas value is read from the current stack frame, so if you'll attempt to - /// read it during the transaction execution, you may receive invalid value. - pub(crate) fn gas_remaining(&self) -> u32 { - self.state.local_state.callstack.current.ergs_remaining - } - pub(crate) fn calculate_computational_gas_used( &self, tracer: &DefaultExecutionTracer, diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/statistics.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/statistics.rs index 06ef4f90340..20113cf34f1 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/statistics.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/implementation/statistics.rs @@ -36,6 +36,7 @@ impl Vm { .get_decommitted_bytecodes_after_timestamp(timestamp_initial), cycles_used: self.state.local_state.monotonic_cycle_counter - cycles_initial, gas_used: gas_remaining_before - gas_remaining_after, + gas_remaining: gas_remaining_after, computational_gas_used, total_log_queries: total_log_queries_count, // This field will be populated by the `RefundTracer` diff --git a/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs b/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs index 7afbaab076d..f1d5dcbab2e 100644 --- a/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs +++ b/core/lib/multivm/src/versions/vm_virtual_blocks/vm.rs @@ -151,10 +151,8 @@ impl VmInterface for Vm { } } - fn has_enough_gas_for_batch_tip(&self) -> bool { - // For this version this overhead has not been calculated and it has not been used with those versions. - // We return some value just in case for backwards compatibility - true + fn gas_remaining(&self) -> u32 { + self.state.local_state.callstack.current.ergs_remaining } fn record_vm_memory_metrics(&self) -> VmMemoryMetrics { diff --git a/core/lib/multivm/src/vm_instance.rs b/core/lib/multivm/src/vm_instance.rs index 44b70db07d8..a742a65f73a 100644 --- a/core/lib/multivm/src/vm_instance.rs +++ b/core/lib/multivm/src/vm_instance.rs @@ -116,8 +116,8 @@ impl VmInterface for VmInstance { dispatch_vm!(self.record_vm_memory_metrics()) } - fn has_enough_gas_for_batch_tip(&self) -> bool { - dispatch_vm!(self.has_enough_gas_for_batch_tip()) + fn gas_remaining(&self) -> u32 { + dispatch_vm!(self.gas_remaining()) } /// Return the results of execution of all batch diff --git a/core/lib/types/src/fee.rs b/core/lib/types/src/fee.rs index 1f10d5d574b..5f32beb2fd4 100644 --- a/core/lib/types/src/fee.rs +++ b/core/lib/types/src/fee.rs @@ -3,12 +3,13 @@ use zksync_utils::ceil_div; use crate::{circuit::CircuitStatistic, U256}; -#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "result")] pub struct TransactionExecutionMetrics { pub initial_storage_writes: usize, pub repeated_storage_writes: usize, pub gas_used: usize, + pub gas_remaining: u32, pub event_topics: u16, pub published_bytecode_bytes: usize, pub l2_l1_long_messages: usize, @@ -27,6 +28,31 @@ pub struct TransactionExecutionMetrics { pub circuit_statistic: CircuitStatistic, } +impl Default for TransactionExecutionMetrics { + fn default() -> Self { + Self { + initial_storage_writes: 0, + repeated_storage_writes: 0, + gas_used: 0, + gas_remaining: u32::MAX, + event_topics: 0, + published_bytecode_bytes: 0, + l2_l1_long_messages: 0, + l2_l1_logs: 0, + contracts_used: 0, + contracts_deployed: 0, + vm_events: 0, + storage_logs: 0, + total_log_queries: 0, + cycles_used: 0, + computational_gas_used: 0, + total_updated_values_size: 0, + pubdata_published: 0, + circuit_statistic: Default::default(), + } + } +} + #[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Fee { /// The limit of gas that are to be spent on the actual transaction. diff --git a/core/lib/zksync_core/src/api_server/execution_sandbox/vm_metrics.rs b/core/lib/zksync_core/src/api_server/execution_sandbox/vm_metrics.rs index c23631ab435..63abec65283 100644 --- a/core/lib/zksync_core/src/api_server/execution_sandbox/vm_metrics.rs +++ b/core/lib/zksync_core/src/api_server/execution_sandbox/vm_metrics.rs @@ -227,6 +227,7 @@ pub(super) fn collect_tx_execution_metrics( initial_storage_writes: writes_metrics.initial_storage_writes, repeated_storage_writes: writes_metrics.repeated_storage_writes, gas_used: result.statistics.gas_used as usize, + gas_remaining: result.statistics.gas_remaining, event_topics, published_bytecode_bytes, l2_l1_long_messages, diff --git a/core/lib/zksync_core/src/state_keeper/batch_executor/main_executor.rs b/core/lib/zksync_core/src/state_keeper/batch_executor/main_executor.rs index 66e31203416..4ccd77bb2bb 100644 --- a/core/lib/zksync_core/src/state_keeper/batch_executor/main_executor.rs +++ b/core/lib/zksync_core/src/state_keeper/batch_executor/main_executor.rs @@ -217,10 +217,7 @@ impl CommandReceiver { } let tx_metrics = ExecutionMetricsForCriteria::new(Some(tx), &tx_result); - - if !vm.has_enough_gas_for_batch_tip() { - return TxExecutionResult::BootloaderOutOfGasForBlockTip; - } + let gas_remaining = vm.gas_remaining(); let (bootloader_dry_run_result, bootloader_dry_run_metrics) = self.dryrun_block_tip(vm); match &bootloader_dry_run_result.result { @@ -231,6 +228,7 @@ impl CommandReceiver { bootloader_dry_run_result: Box::new(bootloader_dry_run_result), compressed_bytecodes, call_tracer_result, + gas_remaining, }, ExecutionResult::Revert { .. } => { unreachable!( diff --git a/core/lib/zksync_core/src/state_keeper/batch_executor/mod.rs b/core/lib/zksync_core/src/state_keeper/batch_executor/mod.rs index acde60b1d41..8f839b7ff87 100644 --- a/core/lib/zksync_core/src/state_keeper/batch_executor/mod.rs +++ b/core/lib/zksync_core/src/state_keeper/batch_executor/mod.rs @@ -32,6 +32,7 @@ pub(crate) enum TxExecutionResult { bootloader_dry_run_result: Box, compressed_bytecodes: Vec, call_tracer_result: Vec, + gas_remaining: u32, }, /// The VM rejected the tx for some reason. RejectedByVm { reason: Halt }, diff --git a/core/lib/zksync_core/src/state_keeper/keeper.rs b/core/lib/zksync_core/src/state_keeper/keeper.rs index ddb580e04b0..49d269b67f8 100644 --- a/core/lib/zksync_core/src/state_keeper/keeper.rs +++ b/core/lib/zksync_core/src/state_keeper/keeper.rs @@ -564,34 +564,50 @@ impl ZkSyncStateKeeper { tx: Transaction, ) -> (SealResolution, TxExecutionResult) { let exec_result = batch_executor.execute_tx(tx.clone()).await; + // All of `TxExecutionResult::BootloaderOutOfGasForTx`, `TxExecutionResult::BootloaderOutOfGasForBlockTip`, + // `Halt::NotEnoughGasProvided` correspond to out-of-gas errors but of different nature. + // - `BootloaderOutOfGasForTx`: it is returned when bootloader stack frame run out of gas before tx execution finished. + // - `BootloaderOutOfGasForBlockTip`: it is returned when bootloader stack frame run out of gas during batch tip dry run. + // - `Halt::NotEnoughGasProvided`: there are checks in bootloader in some places (search for `checkEnoughGas` calls). + // They check if there is more gas in the frame than bootloader estimates it will need. + // This error is returned when such a check fails. Basically, bootloader doesn't continue execution but panics prematurely instead. + // If some transaction fails with any of these errors and is the first transaction in L1 batch, then it's marked as unexecutable. + // Otherwise, `ExcludeAndSeal` resolution is returned, i.e. batch will be sealed and transaction will be included in the next L1 batch. + + let is_first_tx = updates_manager.pending_executed_transactions_len() == 0; let resolution = match &exec_result { - TxExecutionResult::BootloaderOutOfGasForTx => { - AGGREGATION_METRICS - .inc("bootloader_tx_out_of_gas", &SealResolution::ExcludeAndSeal); - SealResolution::ExcludeAndSeal + TxExecutionResult::BootloaderOutOfGasForTx + | TxExecutionResult::BootloaderOutOfGasForBlockTip + | TxExecutionResult::RejectedByVm { + reason: Halt::NotEnoughGasProvided, + } => { + let error_message = match &exec_result { + TxExecutionResult::BootloaderOutOfGasForTx => "bootloader_tx_out_of_gas", + TxExecutionResult::BootloaderOutOfGasForBlockTip => { + "bootloader_batch_tip_out_of_gas" + } + TxExecutionResult::RejectedByVm { + reason: Halt::NotEnoughGasProvided, + } => "not_enough_gas_provided_to_start_tx", + _ => unreachable!(), + }; + let resolution = if is_first_tx { + SealResolution::Unexecutable(error_message.to_string()) + } else { + SealResolution::ExcludeAndSeal + }; + AGGREGATION_METRICS.inc(error_message, &resolution); + resolution } - TxExecutionResult::BootloaderOutOfGasForBlockTip => { - AGGREGATION_METRICS.inc( - "bootloader_block_tip_failed", - &SealResolution::ExcludeAndSeal, - ); - SealResolution::ExcludeAndSeal + TxExecutionResult::RejectedByVm { reason } => { + SealResolution::Unexecutable(reason.to_string()) } - TxExecutionResult::RejectedByVm { reason } => match reason { - Halt::NotEnoughGasProvided => { - AGGREGATION_METRICS.inc( - "not_enough_gas_provided_to_start_tx", - &SealResolution::ExcludeAndSeal, - ); - SealResolution::ExcludeAndSeal - } - _ => SealResolution::Unexecutable(reason.to_string()), - }, TxExecutionResult::Success { tx_result, tx_metrics, bootloader_dry_run_metrics, bootloader_dry_run_result, + gas_remaining, .. } => { let tx_execution_status = &tx_result.result; @@ -649,6 +665,7 @@ impl ZkSyncStateKeeper { gas_count: tx_gas_excluding_writes + tx_writes_l1_gas, cumulative_size: encoding_len, writes_metrics: tx_writes_metrics, + gas_remaining: *gas_remaining, }; let block_data = SealData { execution_metrics: tx_data.execution_metrics @@ -659,6 +676,7 @@ impl ZkSyncStateKeeper { cumulative_size: tx_data.cumulative_size + updates_manager.pending_txs_encoding_size(), writes_metrics: block_writes_metrics, + gas_remaining: *gas_remaining, }; self.sealer.should_seal_l1_batch( diff --git a/core/lib/zksync_core/src/state_keeper/seal_criteria/conditional_sealer.rs b/core/lib/zksync_core/src/state_keeper/seal_criteria/conditional_sealer.rs index b3510260e37..4e9e797b5a0 100644 --- a/core/lib/zksync_core/src/state_keeper/seal_criteria/conditional_sealer.rs +++ b/core/lib/zksync_core/src/state_keeper/seal_criteria/conditional_sealer.rs @@ -135,6 +135,7 @@ impl SequencerSealer { Box::new(criteria::PubDataBytesCriterion), Box::new(criteria::CircuitsCriterion), Box::new(criteria::TxEncodingSizeCriterion), + Box::new(criteria::GasForBatchTipCriterion), ] } } diff --git a/core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/gas_for_batch_tip.rs b/core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/gas_for_batch_tip.rs new file mode 100644 index 00000000000..a0a3d7ca664 --- /dev/null +++ b/core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/gas_for_batch_tip.rs @@ -0,0 +1,99 @@ +use multivm::utils::gas_bootloader_batch_tip_overhead; +use zksync_types::ProtocolVersionId; + +use crate::state_keeper::seal_criteria::{ + SealCriterion, SealData, SealResolution, StateKeeperConfig, +}; + +/// Checks whether we should exclude the transaction because we don't have enough gas for batch tip. +#[derive(Debug)] +pub struct GasForBatchTipCriterion; + +impl SealCriterion for GasForBatchTipCriterion { + fn should_seal( + &self, + _config: &StateKeeperConfig, + _block_open_timestamp_ms: u128, + tx_count: usize, + _block_data: &SealData, + tx_data: &SealData, + protocol_version: ProtocolVersionId, + ) -> SealResolution { + let batch_tip_overhead = gas_bootloader_batch_tip_overhead(protocol_version.into()); + let is_tx_first = tx_count == 1; + + if tx_data.gas_remaining < batch_tip_overhead { + if is_tx_first { + SealResolution::Unexecutable("not_enough_gas_for_batch_tip".to_string()) + } else { + SealResolution::ExcludeAndSeal + } + } else { + SealResolution::NoSeal + } + } + + fn prom_criterion_name(&self) -> &'static str { + "gas_for_batch_tip" + } +} + +#[cfg(test)] +mod tests { + use assert_matches::assert_matches; + + use super::*; + + #[test] + fn test_gas_for_batch_tip_seal_criterion() { + // Create an empty config. + let config = StateKeeperConfig::default(); + + let criterion = GasForBatchTipCriterion; + let protocol_version = ProtocolVersionId::latest(); + + let seal_data = SealData { + gas_remaining: gas_bootloader_batch_tip_overhead(protocol_version.into()), + ..Default::default() + }; + let almost_full_block_resolution = criterion.should_seal( + &config, + Default::default(), + 1, + &seal_data, + &seal_data, + protocol_version, + ); + assert_eq!(almost_full_block_resolution, SealResolution::NoSeal); + + let seal_data = SealData { + gas_remaining: gas_bootloader_batch_tip_overhead(protocol_version.into()) - 1, + ..Default::default() + }; + let full_block_first_tx_resolution = criterion.should_seal( + &config, + Default::default(), + 1, + &seal_data, + &seal_data, + protocol_version, + ); + assert_matches!( + full_block_first_tx_resolution, + SealResolution::Unexecutable(_) + ); + + let full_block_second_tx_resolution = criterion.should_seal( + &config, + Default::default(), + 2, + &seal_data, + &seal_data, + protocol_version, + ); + assert_eq!( + full_block_second_tx_resolution, + SealResolution::ExcludeAndSeal + ); + } +} diff --git a/core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/mod.rs b/core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/mod.rs index 4e30f2a8b60..4772de5c265 100644 --- a/core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/mod.rs +++ b/core/lib/zksync_core/src/state_keeper/seal_criteria/criteria/mod.rs @@ -1,11 +1,12 @@ mod gas; +mod gas_for_batch_tip; mod geometry_seal_criteria; mod pubdata_bytes; mod slots; mod tx_encoding_size; pub(in crate::state_keeper) use self::{ - gas::GasCriterion, geometry_seal_criteria::CircuitsCriterion, - pubdata_bytes::PubDataBytesCriterion, slots::SlotsCriterion, - tx_encoding_size::TxEncodingSizeCriterion, + gas::GasCriterion, gas_for_batch_tip::GasForBatchTipCriterion, + geometry_seal_criteria::CircuitsCriterion, pubdata_bytes::PubDataBytesCriterion, + slots::SlotsCriterion, tx_encoding_size::TxEncodingSizeCriterion, }; diff --git a/core/lib/zksync_core/src/state_keeper/seal_criteria/mod.rs b/core/lib/zksync_core/src/state_keeper/seal_criteria/mod.rs index bf44c7af0ec..b51da77f768 100644 --- a/core/lib/zksync_core/src/state_keeper/seal_criteria/mod.rs +++ b/core/lib/zksync_core/src/state_keeper/seal_criteria/mod.rs @@ -81,6 +81,7 @@ pub struct SealData { pub(super) gas_count: BlockGasCount, pub(super) cumulative_size: usize, pub(super) writes_metrics: DeduplicatedWritesMetrics, + pub(super) gas_remaining: u32, } impl SealData { @@ -100,6 +101,7 @@ impl SealData { gas_count, cumulative_size: transaction.bootloader_encoding_size(), writes_metrics, + gas_remaining: tx_metrics.gas_remaining, } } } diff --git a/core/lib/zksync_core/src/state_keeper/tests/mod.rs b/core/lib/zksync_core/src/state_keeper/tests/mod.rs index c1dc50a8250..6e18e22ee82 100644 --- a/core/lib/zksync_core/src/state_keeper/tests/mod.rs +++ b/core/lib/zksync_core/src/state_keeper/tests/mod.rs @@ -145,6 +145,7 @@ pub(super) fn create_execution_result( contracts_used: 0, cycles_used: 0, gas_used: 0, + gas_remaining: 0, computational_gas_used: 0, total_log_queries, pubdata_published: 0, diff --git a/core/lib/zksync_core/src/state_keeper/tests/tester.rs b/core/lib/zksync_core/src/state_keeper/tests/tester.rs index e3e915cf01c..63b96e82dd0 100644 --- a/core/lib/zksync_core/src/state_keeper/tests/tester.rs +++ b/core/lib/zksync_core/src/state_keeper/tests/tester.rs @@ -259,6 +259,7 @@ pub(crate) fn successful_exec() -> TxExecutionResult { }), compressed_bytecodes: vec![], call_tracer_result: vec![], + gas_remaining: Default::default(), } } @@ -286,6 +287,7 @@ pub(crate) fn successful_exec_with_metrics( }), compressed_bytecodes: vec![], call_tracer_result: vec![], + gas_remaining: Default::default(), } }