From c5115ee3980156d8c348f10f8d08088825cf62b4 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 13:39:30 -0300 Subject: [PATCH 01/10] Optimize `Execution::get_opcode` --- src/execution.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/execution.rs b/src/execution.rs index 34af025b..b87cad12 100644 --- a/src/execution.rs +++ b/src/execution.rs @@ -279,11 +279,12 @@ impl Execution { let pc = self.current_frame()?.pc; let raw_opcode = current_context.code_page.get(pc as usize / 4); + let [a, b, c, d] = raw_opcode.0; let raw_op = match pc % 4 { - 3 => (raw_opcode & u64::MAX.into()).as_u64(), - 2 => ((raw_opcode >> 64) & u64::MAX.into()).as_u64(), - 1 => ((raw_opcode >> 128) & u64::MAX.into()).as_u64(), - _ => ((raw_opcode >> 192) & u64::MAX.into()).as_u64(), // 0 + 3 => a, + 2 => b, + 1 => c, + _ => d, }; Opcode::try_from_raw_opcode(raw_op) From 980f9596a61d775378702fbde87a9f6e125bcec4 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 13:41:04 -0300 Subject: [PATCH 02/10] Optimize `fill_stack_with_zeros` --- src/execution.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/execution.rs b/src/execution.rs index b87cad12..95c7172c 100644 --- a/src/execution.rs +++ b/src/execution.rs @@ -338,12 +338,13 @@ impl Stack { } pub fn fill_with_zeros(&mut self, value: usize) { - for _ in 0..value { - self.stack.push(TaggedValue { + self.stack.resize( + self.stack.len() + value, + TaggedValue { value: U256::zero(), is_pointer: false, - }); - } + }, + ); } pub fn get_with_offset(&self, offset: u16, sp: u32) -> Result { From 8ea37bf4f9fa8a73c1cd8e2d3cb446279532f05f Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 13:44:06 -0300 Subject: [PATCH 03/10] Inline `Opcode` functions --- src/opcode.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opcode.rs b/src/opcode.rs index 48ec936c..7bfb957d 100644 --- a/src/opcode.rs +++ b/src/opcode.rs @@ -141,10 +141,12 @@ impl Opcode { } } +#[inline(always)] fn first_four_bits(value: u8) -> u8 { value & 0x0f } +#[inline(always)] fn second_four_bits(value: u8) -> u8 { (value & 0xf0) >> 4 } From b71782bdb75ae5d6cbe6be2c77a73c06139ca3e2 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 13:45:47 -0300 Subject: [PATCH 04/10] Remove `current_frame_mut` calls in `inexplicit_panic` --- src/op_handlers/ret.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/op_handlers/ret.rs b/src/op_handlers/ret.rs index d7bfdcf9..c88c4d24 100644 --- a/src/op_handlers/ret.rs +++ b/src/op_handlers/ret.rs @@ -92,8 +92,9 @@ pub fn inexplicit_panic(vm: &mut Execution, state: &mut VMState) -> Result Result Date: Tue, 27 Aug 2024 13:49:05 -0300 Subject: [PATCH 05/10] Optimize `clear_registers` function --- src/execution.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/execution.rs b/src/execution.rs index 95c7172c..20375d57 100644 --- a/src/execution.rs +++ b/src/execution.rs @@ -110,9 +110,8 @@ impl Execution { } pub fn clear_registers(&mut self) { - for register in self.registers.iter_mut() { - *register = TaggedValue::new_raw_integer(U256::zero()); - } + let empty_integer = TaggedValue::new_raw_integer(U256::zero()); + self.registers = [empty_integer; 15]; } pub fn clear_flags(&mut self) { From e8c58999805ce6c8991ada33c06021c48f5f7c1d Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 13:53:17 -0300 Subject: [PATCH 06/10] Remove unnecesary `FatPointer` instantiations --- src/op_handlers/ptr_add.rs | 12 +++++------- src/op_handlers/ptr_shrink.rs | 12 +++++------- src/op_handlers/ptr_sub.rs | 11 ++++------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/op_handlers/ptr_add.rs b/src/op_handlers/ptr_add.rs index ae1ebeab..c4aed1ad 100644 --- a/src/op_handlers/ptr_add.rs +++ b/src/op_handlers/ptr_add.rs @@ -2,20 +2,18 @@ use crate::{ eravm_error::{EraVmError, OperandError}, execution::Execution, ptr_operator::{ptr_operands_read, ptr_operands_store}, - value::FatPointer, Opcode, }; pub fn ptr_add(vm: &mut Execution, opcode: &Opcode) -> Result<(), EraVmError> { - let (pointer, diff, src0) = ptr_operands_read(vm, opcode)?; + let (mut pointer, diff, src0) = ptr_operands_read(vm, opcode)?; let (new_offset, overflow) = pointer.offset.overflowing_add(diff); if overflow { return Err(OperandError::Overflow(opcode.variant).into()); } - let new_pointer = FatPointer { - offset: new_offset, - ..pointer - }; - ptr_operands_store(vm, opcode, new_pointer, src0) + + pointer.offset = new_offset; + + ptr_operands_store(vm, opcode, pointer, src0) } diff --git a/src/op_handlers/ptr_shrink.rs b/src/op_handlers/ptr_shrink.rs index 9094865c..f7ad3235 100644 --- a/src/op_handlers/ptr_shrink.rs +++ b/src/op_handlers/ptr_shrink.rs @@ -2,20 +2,18 @@ use crate::{ eravm_error::{EraVmError, OperandError}, execution::Execution, ptr_operator::{ptr_operands_read, ptr_operands_store}, - value::FatPointer, Opcode, }; pub fn ptr_shrink(vm: &mut Execution, opcode: &Opcode) -> Result<(), EraVmError> { - let (pointer, diff, src0) = ptr_operands_read(vm, opcode)?; + let (mut pointer, diff, src0) = ptr_operands_read(vm, opcode)?; let (new_len, overflow) = pointer.len.overflowing_sub(diff); if overflow { return Err(OperandError::Overflow(opcode.variant).into()); } - let new_pointer = FatPointer { - len: new_len, - ..pointer - }; - ptr_operands_store(vm, opcode, new_pointer, src0) + + pointer.len = new_len; + + ptr_operands_store(vm, opcode, pointer, src0) } diff --git a/src/op_handlers/ptr_sub.rs b/src/op_handlers/ptr_sub.rs index 63181740..28558256 100644 --- a/src/op_handlers/ptr_sub.rs +++ b/src/op_handlers/ptr_sub.rs @@ -2,20 +2,17 @@ use crate::{ eravm_error::{EraVmError, OperandError}, execution::Execution, ptr_operator::{ptr_operands_read, ptr_operands_store}, - value::FatPointer, Opcode, }; pub fn ptr_sub(vm: &mut Execution, opcode: &Opcode) -> Result<(), EraVmError> { - let (pointer, diff, src0) = ptr_operands_read(vm, opcode)?; + let (mut pointer, diff, src0) = ptr_operands_read(vm, opcode)?; let (new_offset, overflow) = pointer.offset.overflowing_sub(diff); if overflow { return Err(OperandError::Overflow(opcode.variant).into()); } - let new_pointer = FatPointer { - offset: new_offset, - ..pointer - }; - ptr_operands_store(vm, opcode, new_pointer, src0) + pointer.offset = new_offset; + + ptr_operands_store(vm, opcode, pointer, src0) } From 4561f83e401b088a33d5440f7a7673524274d24e Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 14:58:19 -0300 Subject: [PATCH 07/10] Optimize `ptr_pack` --- src/op_handlers/ptr_pack.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/op_handlers/ptr_pack.rs b/src/op_handlers/ptr_pack.rs index 5f165b78..50a6bfde 100644 --- a/src/op_handlers/ptr_pack.rs +++ b/src/op_handlers/ptr_pack.rs @@ -15,10 +15,18 @@ pub fn ptr_pack(vm: &mut Execution, opcode: &Opcode) -> Result<(), EraVmError> { return Err(OperandError::InvalidSrcPointer(opcode.variant).into()); } - if src1.value & U256::from(u128::MAX) != U256::zero() { + // Check if lower 128 bytes are zero + if (src1.value.0[0] | src1.value.0[1]) != 0 { return Err(OperandError::Src1LowNotZero(opcode.variant).into()); } - let res = TaggedValue::new_pointer(((src0.value << 128) >> 128) | src1.value); + let mut value = U256::zero(); + + value.0[3] = src1.value.0[3]; + value.0[2] = src1.value.0[2]; + value.0[1] = src0.value.0[1]; + value.0[0] = src0.value.0[0]; + + let res = TaggedValue::new_pointer(value); address_operands_store(vm, opcode, res) } From d3d84e1328b23b2419c989b9597549784dcc8954 Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 15:02:48 -0300 Subject: [PATCH 08/10] Optimize `opcode_decommit` --- src/execution.rs | 11 +++++++++++ src/op_handlers/opcode_decommit.rs | 12 +++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/execution.rs b/src/execution.rs index 20375d57..6d3d6548 100644 --- a/src/execution.rs +++ b/src/execution.rs @@ -423,6 +423,17 @@ impl Heap { } } + pub fn store_multiple(&mut self, start_address: u32, values: Vec) { + let mut start = start_address as usize; + let end = (start + values.len() * 32).min(self.heap.len()); + let max_to_store = (end - start) / 32; + + for value in &values[..max_to_store] { + value.to_big_endian(&mut self.heap[start..(start + 32)]); + start += 32; + } + } + pub fn read(&self, address: u32) -> U256 { let mut result = U256::zero(); diff --git a/src/op_handlers/opcode_decommit.rs b/src/op_handlers/opcode_decommit.rs index 16f6faa4..2d85c3b0 100644 --- a/src/op_handlers/opcode_decommit.rs +++ b/src/op_handlers/opcode_decommit.rs @@ -18,8 +18,6 @@ pub fn opcode_decommit( let preimage_len_in_bytes = zkevm_opcode_defs::system_params::NEW_KERNEL_FRAME_MEMORY_STIPEND; - vm.decrease_gas(extra_cost)?; - let code = state .decommit(code_hash) .ok_or(EraVmError::DecommitFailed)?; @@ -36,11 +34,11 @@ pub fn opcode_decommit( let heap = vm.heaps.get_mut(id).ok_or(HeapError::StoreOutOfBounds)?; - let mut address = 0; - for value in code.iter() { - heap.store(address, *value); - address += 32; - } + let mem_expansion_gas_cost = heap.expand_memory(code_len_in_bytes as u32); + + heap.store_multiple(0, code); + + vm.decrease_gas(mem_expansion_gas_cost + extra_cost)?; let pointer = FatPointer { offset: 0, From 8f2ce52081c8f428052f1ede826f093b83545c2f Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 15:05:06 -0300 Subject: [PATCH 09/10] Optimize `retrieve_result` --- src/vm.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index 2cb94089..0b807e8d 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -324,21 +324,11 @@ fn set_pc(vm: &mut Execution, opcode: &Opcode) -> Result<(), EraVmError> { } fn retrieve_result(vm: &mut Execution) -> Result, EraVmError> { - let fat_pointer_src0 = FatPointer::decode(vm.get_register(1).value); - let range = fat_pointer_src0.start..fat_pointer_src0.start + fat_pointer_src0.len; - let mut result: Vec = vec![0; range.len()]; - let end: u32 = (range.end).min( - (vm.heaps - .get(fat_pointer_src0.page) - .ok_or(HeapError::ReadOutOfBounds)? - .len()) as u32, - ); - for (i, j) in (range.start..end).enumerate() { - let current_heap = vm - .heaps - .get(fat_pointer_src0.page) - .ok_or(HeapError::ReadOutOfBounds)?; - result[i] = current_heap.read_byte(j); - } + let ptr = FatPointer::decode(vm.get_register(1).value); + let result = vm + .heaps + .get(ptr.page) + .ok_or(HeapError::ReadOutOfBounds)? + .read_unaligned_from_pointer(&ptr)?; Ok(result) } From c43a510bb6bc12c2bb46b69e112589d6645cf06a Mon Sep 17 00:00:00 2001 From: Julian Ventura Date: Tue, 27 Aug 2024 22:40:44 -0300 Subject: [PATCH 10/10] Update zksync-era commit pointer --- zksync-era | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zksync-era b/zksync-era index 22759011..5714f9a9 160000 --- a/zksync-era +++ b/zksync-era @@ -1 +1 @@ -Subproject commit 2275901178cfab65a2a615286f39aa0af12099ff +Subproject commit 5714f9a951dd6fdf166f24741dc9ababeb6a46cd