From 3feb04d2525d33c6881098e7d08abffa4dca25c2 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 26 Oct 2023 10:20:55 -0400 Subject: [PATCH 1/8] Refactor wcopy syscalls --- evm/src/cpu/kernel/asm/memory/syscalls.asm | 104 +++++++-------------- 1 file changed, 36 insertions(+), 68 deletions(-) diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index 1820056715..ad041c44e3 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -70,21 +70,19 @@ calldataload_large_offset: %stack (kexit_info, i) -> (kexit_info, 0) EXIT_KERNEL -// Macro for {CALLDATA,CODE,RETURNDATA}COPY (W_copy in Yellow Paper). +// Macro for {CALLDATA, RETURNDATA}COPY (W_copy in Yellow Paper). %macro wcopy(segment, context_metadata_size) // stack: kexit_info, dest_offset, offset, size - PUSH @GAS_VERYLOW - DUP5 - // stack: size, Gverylow, kexit_info, dest_offset, offset, size - ISZERO %jumpi(wcopy_empty) - // stack: Gverylow, kexit_info, dest_offset, offset, size - DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD %charge_gas + %wcopy_charge_gas %stack (kexit_info, dest_offset, offset, size) -> (dest_offset, size, kexit_info, dest_offset, offset, size) %add_or_fault // stack: expanded_num_bytes, kexit_info, dest_offset, offset, size, kexit_info DUP1 %ensure_reasonable_offset %update_mem_bytes + // stack: kexit_info, dest_offset, offset, size, kexit_info + DUP4 DUP4 %add_or_fault // Overflow check + %mload_context_metadata($context_metadata_size) LT %jumpi(fault_exception) // Data len check %mload_context_metadata($context_metadata_size) // stack: total_size, kexit_info, dest_offset, offset, size @@ -92,30 +90,20 @@ calldataload_large_offset: // stack: offset, total_size, kexit_info, dest_offset, offset, size GT %jumpi(wcopy_large_offset) + // stack: kexit_info, dest_offset, offset, size PUSH $segment - %mload_context_metadata($context_metadata_size) - // stack: total_size, segment, kexit_info, dest_offset, offset, size - DUP6 DUP6 ADD - // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size - LT %jumpi(wcopy_within_bounds) - - %mload_context_metadata($context_metadata_size) - // stack: total_size, segment, kexit_info, dest_offset, offset, size - DUP6 DUP6 ADD - // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size - SUB // extra_size = offset + size - total_size - // stack: extra_size, segment, kexit_info, dest_offset, offset, size - DUP1 DUP7 SUB - // stack: copy_size = size - extra_size, extra_size, segment, kexit_info, dest_offset, offset, size - - // Compute the new dest_offset after actual copies, at which we will start padding with zeroes. - DUP1 DUP6 ADD - // stack: new_dest_offset, copy_size, extra_size, segment, kexit_info, dest_offset, offset, size + PUSH wcopy_within_bounds + JUMP +%endmacro - GET_CONTEXT - %stack (context, new_dest_offset, copy_size, extra_size, segment, kexit_info, dest_offset, offset, size) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, segment, offset, copy_size, wcopy_over_range, new_dest_offset, extra_size, kexit_info) - %jump(memcpy_bytes) +%macro wcopy_charge_gas + // stack: kexit_info, dest_offset, offset, size + PUSH @GAS_VERYLOW + DUP5 + // stack: size, Gverylow, kexit_info, dest_offset, offset, size + ISZERO %jumpi(wcopy_empty) + // stack: Gverylow, kexit_info, dest_offset, offset, size + DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD %charge_gas %endmacro wcopy_within_bounds: @@ -125,15 +113,6 @@ wcopy_within_bounds: (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, segment, offset, size, wcopy_after, kexit_info) %jump(memcpy_bytes) - -// Same as wcopy_large_offset, but without `offset` in the stack. -wcopy_over_range: - // stack: dest_offset, size, kexit_info - GET_CONTEXT - %stack (context, dest_offset, size, kexit_info) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, size, wcopy_after, kexit_info) - %jump(memset) - wcopy_empty: // stack: Gverylow, kexit_info, dest_offset, offset, size %charge_gas @@ -156,60 +135,49 @@ global sys_calldatacopy: %wcopy(@SEGMENT_CALLDATA, @CTX_METADATA_CALLDATA_SIZE) global sys_codecopy: - %wcopy(@SEGMENT_CODE, @CTX_METADATA_CODE_SIZE) + %codecopy(@SEGMENT_CODE, @CTX_METADATA_CODE_SIZE) -// Same as %wcopy but with overflow checks. global sys_returndatacopy: + %wcopy(@SEGMENT_RETURNDATA, @CTX_METADATA_RETURNDATA_SIZE) + +%macro codecopy(segment, context_metadata_size) // stack: kexit_info, dest_offset, offset, size - PUSH @GAS_VERYLOW - // stack: Gverylow, kexit_info, dest_offset, offset, size - DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD %charge_gas + %wcopy_charge_gas %stack (kexit_info, dest_offset, offset, size) -> (dest_offset, size, kexit_info, dest_offset, offset, size) %add_or_fault // stack: expanded_num_bytes, kexit_info, dest_offset, offset, size, kexit_info DUP1 %ensure_reasonable_offset %update_mem_bytes - // stack: kexit_info, dest_offset, offset, size, kexit_info - DUP4 DUP4 %add_or_fault // Overflow check - %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) LT %jumpi(fault_exception) // Data len check - - // stack: kexit_info, dest_offset, offset, size - DUP4 - // stack: size, kexit_info, dest_offset, offset, size - ISZERO %jumpi(returndatacopy_empty) - %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) + %mload_context_metadata($context_metadata_size) // stack: total_size, kexit_info, dest_offset, offset, size DUP4 // stack: offset, total_size, kexit_info, dest_offset, offset, size GT %jumpi(wcopy_large_offset) - PUSH @SEGMENT_RETURNDATA - %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) - // stack: total_size, returndata_segment, kexit_info, dest_offset, offset, size + PUSH $segment + %mload_context_metadata($context_metadata_size) + // stack: total_size, segment, kexit_info, dest_offset, offset, size DUP6 DUP6 ADD - // stack: offset + size, total_size, returndata_segment, kexit_info, dest_offset, offset, size + // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size LT %jumpi(wcopy_within_bounds) - %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) - // stack: total_size, returndata_segment, kexit_info, dest_offset, offset, size + %mload_context_metadata($context_metadata_size) + // stack: total_size, segment, kexit_info, dest_offset, offset, size DUP6 DUP6 ADD - // stack: offset + size, total_size, returndata_segment, kexit_info, dest_offset, offset, size + // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size SUB // extra_size = offset + size - total_size - // stack: extra_size, returndata_segment, kexit_info, dest_offset, offset, size + // stack: extra_size, segment, kexit_info, dest_offset, offset, size DUP1 DUP7 SUB - // stack: copy_size = size - extra_size, extra_size, returndata_segment, kexit_info, dest_offset, offset, size + // stack: copy_size = size - extra_size, extra_size, segment, kexit_info, dest_offset, offset, size // Compute the new dest_offset after actual copies, at which we will start padding with zeroes. DUP1 DUP6 ADD - // stack: new_dest_offset, copy_size, extra_size, returndata_segment, kexit_info, dest_offset, offset, size + // stack: new_dest_offset, copy_size, extra_size, segment, kexit_info, dest_offset, offset, size GET_CONTEXT - %stack (context, new_dest_offset, copy_size, extra_size, returndata_segment, kexit_info, dest_offset, offset, size) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, returndata_segment, offset, copy_size, wcopy_over_range, new_dest_offset, extra_size, kexit_info) + %stack (context, new_dest_offset, copy_size, extra_size, segment, kexit_info, dest_offset, offset, size) -> + (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, segment, offset, copy_size, wcopy_large_offset, kexit_info, new_dest_offset, offset, extra_size) %jump(memcpy_bytes) - -returndatacopy_empty: - %stack (kexit_info, dest_offset, offset, size) -> (kexit_info) - EXIT_KERNEL +%endmacro From a1b178f6c7c22f84830b03db86fe810d3f79ef34 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 26 Oct 2023 11:21:10 -0400 Subject: [PATCH 2/8] Refactor memcpy --- evm/src/cpu/kernel/asm/memory/memcpy.asm | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/evm/src/cpu/kernel/asm/memory/memcpy.asm b/evm/src/cpu/kernel/asm/memory/memcpy.asm index e737dc33ca..55b773eb17 100644 --- a/evm/src/cpu/kernel/asm/memory/memcpy.asm +++ b/evm/src/cpu/kernel/asm/memory/memcpy.asm @@ -42,12 +42,6 @@ global memcpy: // Continue the loop. %jump(memcpy) -memcpy_finish: - // stack: DST, SRC, count, retdest - %pop7 - // stack: retdest - JUMP - %macro memcpy %stack (dst: 3, src: 3, count) -> (dst, src, count, %%after) %jump(memcpy) @@ -63,7 +57,7 @@ global memcpy_bytes: // stack: count, DST, SRC, count, retdest ISZERO // stack: count == 0, DST, SRC, count, retdest - %jumpi(memcpy_bytes_empty) + %jumpi(memcpy_finish) // stack: DST, SRC, count, retdest @@ -126,12 +120,8 @@ memcpy_bytes_finish: MSTORE_32BYTES // stack: DST, SRC, count, retdest - %pop7 - // stack: retdest - JUMP - -memcpy_bytes_empty: - // stack: DST, SRC, 0, retdest +memcpy_finish: + // stack: DST, SRC, count, retdest %pop7 // stack: retdest JUMP From a9e47afc072cc2fb9d98709f2fa2dad06870c61d Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 26 Oct 2023 15:24:53 -0400 Subject: [PATCH 3/8] Refactor codecopy --- evm/src/cpu/kernel/asm/account_code.asm | 104 --------------------- evm/src/cpu/kernel/asm/memory/syscalls.asm | 86 ++++++++++++++--- 2 files changed, 72 insertions(+), 118 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index ee19819837..4dddc6dfd6 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -80,110 +80,6 @@ global extcodesize: // stack: extcodesize(address), retdest SWAP1 JUMP -%macro extcodecopy - // stack: address, dest_offset, offset, size - %stack (address, dest_offset, offset, size) -> (address, dest_offset, offset, size, %%after) - %jump(extcodecopy) -%%after: -%endmacro - -// Pre stack: kexit_info, address, dest_offset, offset, size -// Post stack: (empty) -global sys_extcodecopy: - %stack (kexit_info, address, dest_offset, offset, size) - -> (address, dest_offset, offset, size, kexit_info) - %u256_to_addr DUP1 %insert_accessed_addresses - // stack: cold_access, address, dest_offset, offset, size, kexit_info - PUSH @GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS - MUL - PUSH @GAS_WARMACCESS - ADD - // stack: Gaccess, address, dest_offset, offset, size, kexit_info - - DUP5 - // stack: size, Gaccess, address, dest_offset, offset, size, kexit_info - ISZERO %jumpi(sys_extcodecopy_empty) - - // stack: Gaccess, address, dest_offset, offset, size, kexit_info - DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD - %stack (gas, address, dest_offset, offset, size, kexit_info) -> (gas, kexit_info, address, dest_offset, offset, size) - %charge_gas - - %stack (kexit_info, address, dest_offset, offset, size) -> (dest_offset, size, kexit_info, address, dest_offset, offset, size) - %add_or_fault - // stack: expanded_num_bytes, kexit_info, address, dest_offset, offset, size - DUP1 %ensure_reasonable_offset - %update_mem_bytes - - %stack (kexit_info, address, dest_offset, offset, size) -> (address, dest_offset, offset, size, kexit_info) - %extcodecopy - // stack: kexit_info - EXIT_KERNEL - -sys_extcodecopy_empty: - %stack (Gaccess, address, dest_offset, offset, size, kexit_info) -> (Gaccess, kexit_info) - %charge_gas - EXIT_KERNEL - - -// Pre stack: address, dest_offset, offset, size, retdest -// Post stack: (empty) -global extcodecopy: - // stack: address, dest_offset, offset, size, retdest - %stack (address, dest_offset, offset, size, retdest) - -> (address, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, extcodecopy_contd, size, offset, dest_offset, retdest) - %jump(load_code) - -extcodecopy_contd: - // stack: code_size, size, offset, dest_offset, retdest - DUP1 DUP4 - // stack: offset, code_size, code_size, size, offset, dest_offset, retdest - GT %jumpi(extcodecopy_large_offset) - - // stack: code_size, size, offset, dest_offset, retdest - DUP3 DUP3 ADD - // stack: offset + size, code_size, size, offset, dest_offset, retdest - DUP2 GT %jumpi(extcodecopy_within_bounds) - - // stack: code_size, size, offset, dest_offset, retdest - DUP3 DUP3 ADD - // stack: offset + size, code_size, size, offset, dest_offset, retdest - SUB - // stack: extra_size = offset + size - code_size, size, offset, dest_offset, retdest - DUP1 DUP3 SUB - // stack: copy_size = size - extra_size, extra_size, size, offset, dest_offset, retdest - - // Compute the new dest_offset after actual copies, at which we will start padding with zeroes. - DUP1 DUP6 ADD - // stack: new_dest_offset, copy_size, extra_size, size, offset, dest_offset, retdest - - GET_CONTEXT - %stack (context, new_dest_offset, copy_size, extra_size, size, offset, dest_offset, retdest) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, offset, copy_size, extcodecopy_end, new_dest_offset, extra_size, retdest) - %jump(memcpy_bytes) - -extcodecopy_within_bounds: - // stack: code_size, size, offset, dest_offset, retdest - GET_CONTEXT - %stack (context, code_size, size, offset, dest_offset, retdest) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, offset, size, retdest) - %jump(memcpy_bytes) - -// Same as extcodecopy_large_offset, but without `offset` in the stack. -extcodecopy_end: - // stack: dest_offset, size, retdest - GET_CONTEXT - %stack (context, dest_offset, size, retdest) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, size, retdest) - %jump(memset) - -extcodecopy_large_offset: - // offset is larger than the code size. So we just have to write zeros. - // stack: code_size, size, offset, dest_offset, retdest - GET_CONTEXT - %stack (context, code_size, size, offset, dest_offset, retdest) -> (context, @SEGMENT_MAIN_MEMORY, dest_offset, size, retdest) - %jump(memset) - // Loads the code at `address` into memory, at the given context and segment, starting at offset 0. // Checks that the hash of the loaded code corresponds to the `codehash` in the state trie. // Pre stack: address, ctx, segment, retdest diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index ad041c44e3..dd4787fe83 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -106,6 +106,10 @@ calldataload_large_offset: DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD %charge_gas %endmacro + +codecopy_within_bounds: + // stack: total_size, segment, kexit_info, dest_offset, offset, size + POP wcopy_within_bounds: // stack: segment, kexit_info, dest_offset, offset, size GET_CONTEXT @@ -119,6 +123,10 @@ wcopy_empty: %stack (kexit_info, dest_offset, offset, size) -> (kexit_info) EXIT_KERNEL + +codecopy_large_offset: + // stack: total_size, kexit_info, dest_offset, offset, size + POP wcopy_large_offset: // offset is larger than the size of the {CALLDATA,CODE,RETURNDATA}. So we just have to write zeros. // stack: kexit_info, dest_offset, offset, size @@ -131,16 +139,19 @@ wcopy_after: // stack: kexit_info EXIT_KERNEL +// Pre stack: kexit_info, dest_offset, offset, size +// Post stack: (empty) global sys_calldatacopy: %wcopy(@SEGMENT_CALLDATA, @CTX_METADATA_CALLDATA_SIZE) -global sys_codecopy: - %codecopy(@SEGMENT_CODE, @CTX_METADATA_CODE_SIZE) - +// Pre stack: kexit_info, dest_offset, offset, size +// Post stack: (empty) global sys_returndatacopy: %wcopy(@SEGMENT_RETURNDATA, @CTX_METADATA_RETURNDATA_SIZE) -%macro codecopy(segment, context_metadata_size) +// Pre stack: kexit_info, dest_offset, offset, size +// Post stack: (empty) +global sys_codecopy: // stack: kexit_info, dest_offset, offset, size %wcopy_charge_gas @@ -150,20 +161,67 @@ global sys_returndatacopy: DUP1 %ensure_reasonable_offset %update_mem_bytes - %mload_context_metadata($context_metadata_size) + %mload_context_metadata(@CTX_METADATA_CODE_SIZE) + // stack: code_size, kexit_info, dest_offset, offset, size, + %codecopy_after_checks(@SEGMENT_CODE) + + +// Pre stack: kexit_info, address, dest_offset, offset, size +// Post stack: (empty) +global sys_extcodecopy: + %stack (kexit_info, address, dest_offset, offset, size) + -> (address, dest_offset, offset, size, kexit_info) + %u256_to_addr DUP1 %insert_accessed_addresses + // stack: cold_access, address, dest_offset, offset, size, kexit_info + PUSH @GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS + MUL + PUSH @GAS_WARMACCESS + ADD + // stack: Gaccess, address, dest_offset, offset, size, kexit_info + + DUP5 + // stack: size, Gaccess, address, dest_offset, offset, size, kexit_info + ISZERO %jumpi(sys_extcodecopy_empty) + + // stack: Gaccess, address, dest_offset, offset, size, kexit_info + DUP5 %num_bytes_to_num_words %mul_const(@GAS_COPY) ADD + %stack (gas, address, dest_offset, offset, size, kexit_info) -> (gas, kexit_info, address, dest_offset, offset, size) + %charge_gas + + %stack (kexit_info, address, dest_offset, offset, size) -> (dest_offset, size, kexit_info, address, dest_offset, offset, size) + %add_or_fault + // stack: expanded_num_bytes, kexit_info, address, dest_offset, offset, size + DUP1 %ensure_reasonable_offset + %update_mem_bytes + + %stack (kexit_info, address, dest_offset, offset, size) -> + (address, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, extcodecopy_contd, kexit_info, dest_offset, offset, size) + %jump(load_code) + +sys_extcodecopy_empty: + %stack (Gaccess, address, dest_offset, offset, size, kexit_info) -> (Gaccess, kexit_info) + %charge_gas + EXIT_KERNEL + +extcodecopy_contd: + // stack: code_size, kexit_info, dest_offset, offset, size + %codecopy_after_checks(@SEGMENT_KERNEL_ACCOUNT_CODE) + + +// The internal logic is similar to wcopy, but handles range overflow differently. +// It is used for both CODECOPY and EXTCODECOPY. +%macro codecopy_after_checks(segment) // stack: total_size, kexit_info, dest_offset, offset, size - DUP4 - // stack: offset, total_size, kexit_info, dest_offset, offset, size - GT %jumpi(wcopy_large_offset) + DUP1 DUP5 + // stack: offset, total_size, total_size, kexit_info, dest_offset, offset, size + GT %jumpi(codecopy_large_offset) - PUSH $segment - %mload_context_metadata($context_metadata_size) + PUSH $segment SWAP1 // stack: total_size, segment, kexit_info, dest_offset, offset, size - DUP6 DUP6 ADD - // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size - LT %jumpi(wcopy_within_bounds) + DUP1 DUP7 DUP7 ADD + // stack: offset + size, total_size, total_size, segment, kexit_info, dest_offset, offset, size + LT %jumpi(codecopy_within_bounds) - %mload_context_metadata($context_metadata_size) // stack: total_size, segment, kexit_info, dest_offset, offset, size DUP6 DUP6 ADD // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size From ade5b8c39b3ed0b500e6f50a6765b8edce2ed36b Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 26 Oct 2023 15:46:55 -0400 Subject: [PATCH 4/8] Fix --- evm/src/cpu/kernel/asm/memory/syscalls.asm | 53 ++++++++++++---------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index dd4787fe83..6cde6c7f80 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -91,7 +91,9 @@ calldataload_large_offset: GT %jumpi(wcopy_large_offset) // stack: kexit_info, dest_offset, offset, size + GET_CONTEXT PUSH $segment + // stack: segment, context, kexit_info, dest_offset, offset, size PUSH wcopy_within_bounds JUMP %endmacro @@ -108,13 +110,13 @@ calldataload_large_offset: codecopy_within_bounds: - // stack: total_size, segment, kexit_info, dest_offset, offset, size + // stack: total_size, segment, src_ctx, kexit_info, dest_offset, offset, size POP wcopy_within_bounds: - // stack: segment, kexit_info, dest_offset, offset, size + // stack: segment, src_ctx, kexit_info, dest_offset, offset, size GET_CONTEXT - %stack (context, segment, kexit_info, dest_offset, offset, size) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, segment, offset, size, wcopy_after, kexit_info) + %stack (context, segment, src_ctx, kexit_info, dest_offset, offset, size) -> + (context, @SEGMENT_MAIN_MEMORY, dest_offset, src_ctx, segment, offset, size, wcopy_after, kexit_info) %jump(memcpy_bytes) wcopy_empty: @@ -125,8 +127,8 @@ wcopy_empty: codecopy_large_offset: - // stack: total_size, kexit_info, dest_offset, offset, size - POP + // stack: total_size, src_ctx, kexit_info, dest_offset, offset, size + %pop2 wcopy_large_offset: // offset is larger than the size of the {CALLDATA,CODE,RETURNDATA}. So we just have to write zeros. // stack: kexit_info, dest_offset, offset, size @@ -161,8 +163,9 @@ global sys_codecopy: DUP1 %ensure_reasonable_offset %update_mem_bytes + GET_CONTEXT %mload_context_metadata(@CTX_METADATA_CODE_SIZE) - // stack: code_size, kexit_info, dest_offset, offset, size, + // stack: code_size, ctx, kexit_info, dest_offset, offset, size %codecopy_after_checks(@SEGMENT_CODE) @@ -195,7 +198,7 @@ global sys_extcodecopy: %update_mem_bytes %stack (kexit_info, address, dest_offset, offset, size) -> - (address, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, extcodecopy_contd, kexit_info, dest_offset, offset, size) + (address, 0, @SEGMENT_KERNEL_ACCOUNT_CODE, extcodecopy_contd, 0, kexit_info, dest_offset, offset, size) %jump(load_code) sys_extcodecopy_empty: @@ -204,38 +207,38 @@ sys_extcodecopy_empty: EXIT_KERNEL extcodecopy_contd: - // stack: code_size, kexit_info, dest_offset, offset, size + // stack: code_size, src_ctx, kexit_info, dest_offset, offset, size %codecopy_after_checks(@SEGMENT_KERNEL_ACCOUNT_CODE) // The internal logic is similar to wcopy, but handles range overflow differently. // It is used for both CODECOPY and EXTCODECOPY. %macro codecopy_after_checks(segment) - // stack: total_size, kexit_info, dest_offset, offset, size - DUP1 DUP5 - // stack: offset, total_size, total_size, kexit_info, dest_offset, offset, size + // stack: total_size, src_ctx, kexit_info, dest_offset, offset, size + DUP1 DUP6 + // stack: offset, total_size, total_size, src_ctx, kexit_info, dest_offset, offset, size GT %jumpi(codecopy_large_offset) PUSH $segment SWAP1 - // stack: total_size, segment, kexit_info, dest_offset, offset, size - DUP1 DUP7 DUP7 ADD - // stack: offset + size, total_size, total_size, segment, kexit_info, dest_offset, offset, size + // stack: total_size, segment, src_ctx, kexit_info, dest_offset, offset, size + DUP1 DUP8 DUP8 ADD + // stack: offset + size, total_size, total_size, segment, src_ctx, kexit_info, dest_offset, offset, size LT %jumpi(codecopy_within_bounds) - // stack: total_size, segment, kexit_info, dest_offset, offset, size - DUP6 DUP6 ADD - // stack: offset + size, total_size, segment, kexit_info, dest_offset, offset, size + // stack: total_size, segment, src_ctx, kexit_info, dest_offset, offset, size + DUP7 DUP7 ADD + // stack: offset + size, total_size, segment, src_ctx, kexit_info, dest_offset, offset, size SUB // extra_size = offset + size - total_size - // stack: extra_size, segment, kexit_info, dest_offset, offset, size - DUP1 DUP7 SUB - // stack: copy_size = size - extra_size, extra_size, segment, kexit_info, dest_offset, offset, size + // stack: extra_size, segment, src_ctx, kexit_info, dest_offset, offset, size + DUP1 DUP8 SUB + // stack: copy_size = size - extra_size, extra_size, segment, src_ctx, kexit_info, dest_offset, offset, size // Compute the new dest_offset after actual copies, at which we will start padding with zeroes. - DUP1 DUP6 ADD - // stack: new_dest_offset, copy_size, extra_size, segment, kexit_info, dest_offset, offset, size + DUP1 DUP7 ADD + // stack: new_dest_offset, copy_size, extra_size, segment, src_ctx, kexit_info, dest_offset, offset, size GET_CONTEXT - %stack (context, new_dest_offset, copy_size, extra_size, segment, kexit_info, dest_offset, offset, size) -> - (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, segment, offset, copy_size, wcopy_large_offset, kexit_info, new_dest_offset, offset, extra_size) + %stack (context, new_dest_offset, copy_size, extra_size, segment, src_ctx, kexit_info, dest_offset, offset, size) -> + (context, @SEGMENT_MAIN_MEMORY, dest_offset, src_ctx, segment, offset, copy_size, wcopy_large_offset, kexit_info, new_dest_offset, offset, extra_size) %jump(memcpy_bytes) %endmacro From 75fdd342f587930249b514a44bde0da002faba72 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 26 Oct 2023 15:59:40 -0400 Subject: [PATCH 5/8] Fix calldatacopy --- evm/src/cpu/kernel/asm/memory/syscalls.asm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index 6cde6c7f80..03c05f21b5 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -80,9 +80,6 @@ calldataload_large_offset: // stack: expanded_num_bytes, kexit_info, dest_offset, offset, size, kexit_info DUP1 %ensure_reasonable_offset %update_mem_bytes - // stack: kexit_info, dest_offset, offset, size, kexit_info - DUP4 DUP4 %add_or_fault // Overflow check - %mload_context_metadata($context_metadata_size) LT %jumpi(fault_exception) // Data len check %mload_context_metadata($context_metadata_size) // stack: total_size, kexit_info, dest_offset, offset, size @@ -149,6 +146,9 @@ global sys_calldatacopy: // Pre stack: kexit_info, dest_offset, offset, size // Post stack: (empty) global sys_returndatacopy: + DUP4 DUP4 %add_or_fault // Overflow check + %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) LT %jumpi(fault_exception) // Data len check + %wcopy(@SEGMENT_RETURNDATA, @CTX_METADATA_RETURNDATA_SIZE) // Pre stack: kexit_info, dest_offset, offset, size From 15a9e9928a896cfbdf1916861e4e66ffaa297d3e Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Thu, 26 Oct 2023 17:08:40 -0400 Subject: [PATCH 6/8] Fix test on interpreter side --- evm/src/cpu/kernel/interpreter.rs | 21 ++++++++++++++++++++- evm/src/cpu/kernel/tests/account_code.rs | 8 +++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 4ba6e9dcfe..53844ac51e 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -426,7 +426,7 @@ impl<'a> Interpreter<'a> { 0xf6 => self.run_get_context(), // "GET_CONTEXT", 0xf7 => self.run_set_context(), // "SET_CONTEXT", 0xf8 => self.run_mload_32bytes(), // "MLOAD_32BYTES", - 0xf9 => todo!(), // "EXIT_KERNEL", + 0xf9 => self.run_exit_kernel(), // "EXIT_KERNEL", 0xfa => todo!(), // "STATICCALL", 0xfb => self.run_mload_general(), // "MLOAD_GENERAL", 0xfc => self.run_mstore_general(), // "MSTORE_GENERAL", @@ -1126,6 +1126,25 @@ impl<'a> Interpreter<'a> { } } + fn run_exit_kernel(&mut self) { + let _dummy = self.pop(); // not sure why we need this extra pop on the interpreter + let kexit_info = self.pop(); + + let kexit_info_u64 = kexit_info.0[0]; + let program_counter = kexit_info_u64 as u32 as usize; + let is_kernel_mode_val = (kexit_info_u64 >> 32) as u32; + assert!(is_kernel_mode_val == 0 || is_kernel_mode_val == 1); + let is_kernel_mode = is_kernel_mode_val != 0; + let gas_used_val = kexit_info.0[3]; + if TryInto::::try_into(gas_used_val).is_err() { + panic!("Gas overflow"); + } + + self.generation_state.registers.program_counter = program_counter; + self.generation_state.registers.is_kernel = is_kernel_mode; + self.generation_state.registers.gas_used = gas_used_val; + } + pub(crate) fn stack_len(&self) -> usize { self.generation_state.registers.stack_len } diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index f4c18fe603..7735578937 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -7,6 +7,7 @@ use keccak_hash::keccak; use rand::{thread_rng, Rng}; use crate::cpu::kernel::aggregator::KERNEL; +use crate::cpu::kernel::constants::context_metadata::ContextMetadata::GasLimit; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; @@ -142,7 +143,11 @@ fn test_extcodecopy() -> Result<()> { // Prepare the interpreter by inserting the account in the state trie. prepare_interpreter(&mut interpreter, address, &account)?; - let extcodecopy = KERNEL.global_labels["extcodecopy"]; + interpreter.generation_state.memory.contexts[interpreter.context].segments + [Segment::ContextMetadata as usize] + .set(GasLimit as usize, U256::from(1000000000000u64) << 192); + + let extcodecopy = KERNEL.global_labels["sys_extcodecopy"]; // Put random data in main memory and the `KernelAccountCode` segment for realism. let mut rng = thread_rng(); @@ -169,6 +174,7 @@ fn test_extcodecopy() -> Result<()> { interpreter.push(offset.into()); interpreter.push(dest_offset.into()); interpreter.push(U256::from_big_endian(address.as_bytes())); + interpreter.push(0.into()); // kexit_info interpreter.generation_state.inputs.contract_code = HashMap::from([(keccak(&code), code.clone())]); interpreter.run()?; From 7447959fad11709233a12533a5cf729551d8beaa Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Fri, 27 Oct 2023 11:15:23 -0400 Subject: [PATCH 7/8] Fix kexit_info in test --- evm/src/cpu/kernel/interpreter.rs | 1 - evm/src/cpu/kernel/tests/account_code.rs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 53844ac51e..1b9160d695 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -1127,7 +1127,6 @@ impl<'a> Interpreter<'a> { } fn run_exit_kernel(&mut self) { - let _dummy = self.pop(); // not sure why we need this extra pop on the interpreter let kexit_info = self.pop(); let kexit_info_u64 = kexit_info.0[0]; diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index 7735578937..278593787d 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -169,12 +169,11 @@ fn test_extcodecopy() -> Result<()> { interpreter.generation_state.registers.program_counter = extcodecopy; interpreter.pop(); assert!(interpreter.stack().is_empty()); - interpreter.push(0xDEADBEEFu32.into()); interpreter.push(size.into()); interpreter.push(offset.into()); interpreter.push(dest_offset.into()); interpreter.push(U256::from_big_endian(address.as_bytes())); - interpreter.push(0.into()); // kexit_info + interpreter.push(0xDEADBEEFu32.into()); // kexit_info interpreter.generation_state.inputs.contract_code = HashMap::from([(keccak(&code), code.clone())]); interpreter.run()?; From 6f52b76d030d86cf6e634be7307ac2ca2d8af396 Mon Sep 17 00:00:00 2001 From: Robin Salen Date: Fri, 27 Oct 2023 11:16:47 -0400 Subject: [PATCH 8/8] Review --- evm/src/cpu/kernel/asm/memory/syscalls.asm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index 03c05f21b5..3a8c16184d 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -91,8 +91,7 @@ calldataload_large_offset: GET_CONTEXT PUSH $segment // stack: segment, context, kexit_info, dest_offset, offset, size - PUSH wcopy_within_bounds - JUMP + %jump(wcopy_within_bounds) %endmacro %macro wcopy_charge_gas